// 此文件不考虑 cmd amd 等规范 ， 仅仅 IIFE 来解决 命名冲突的问题
// svg2.0 的版本 优化
///////////////////////////////////////
// 私有参数参数 ///////////////////////
/////////////////////////////////////
var that = undefined, // 重新定向
  userAgent = navigator.userAgent, // 获取浏览器信息
  agentFrom = userAgent.indexOf('Firefox') === -1 ? 'noFirefox' : 'Firefox', // 判断是否是火狐浏览器 解决火狐不兼容的问题  需要给容器设置 绝对定位或者相对定位
  eventsArr = [], // 事件数组
  types = ['rect', 'polygon', 'polyline', 'overPolyline', 'closeOverPolyline'], // 所有可绘制的图形类型
  rColor = '#FF00FF',
  pColor = '#0000FF',
  plColor = '#FF0000'; // 矩形边框颜色

/**
 * @param options
 * @constructorf
 */
function OcrPublicClass(options) {
  // ① 参数校验
  assert(Object.prototype.toString.call(SVG) === '[object Function]', 'SvgToImg is Depend on SVG');
  assert(Object.prototype.toString.call(options) === '[object Object]', 'options is must be a object');

  // ② 参数初始化
  that = this; // 引用
  that.vm = options || {}; // that.vm 代表业务参数
  that.dm = {}; // that.dm 代表内部参数

  // ③ 调用内部初始化函数
  that.initVm();
  that.initPrivateData();
  that.init();
}

// 初始化业务参数
OcrPublicClass.prototype.initVm = function () {
  this.vm.el = this.vm.el || 'drawing';
  this.vm.height = this.vm.height || '100%';
  this.vm.width = this.vm.width || '100%';
  this.vm.currentDrawData = this.vm.currentDrawData || {};
  this.vm.currentId = this.vm.currentId || 0;
  this.vm.selectId = this.vm.selectId || 0;
  this.vm.list = this.vm.list || {};
  this.vm.isDisableRightKey = this.vm.isDisableRightKey || false;
  this.vm.zoom = this.vm.zoom || 1;
  this.vm.maxZoom = this.vm.maxZoom || 15;
  this.vm.minZoom = this.vm.minZoom || 0.02;
  this.vm.dragPointSize = this.vm.dragPointSize || 10;
  this.vm.strokeWidth = this.vm.strokeWidth || 2;
  this.vm.textSize = this.vm.textSize || 12;
  this.vm.imgData = this.vm.imgData || {
    imgPath: 'http://ainote.iflytek.com/static/images/reg_bg.jpg',
    x: 0,
    y: 0,
    width: 0,
    height: 0
  };
  this.vm.currentPolyLineId = this.vm.currentPolyLineId || '';
  this.vm.leaveEnd = this.vm.leaveEnd || false
};

// 初始化内部参数
OcrPublicClass.prototype.initPrivateData = function () {
  this.dm = {
    draw: null, // SVG drawing 实例对象
    drawImg: null, // SVG img 实例对象
    defaultGroup: null, // svg 组别 用来存放 svg 图形 等 （所有的图形放在这里 ，缩放也是如此）
    currentDraw: null, // 当前绘制的 SVG图形 实例对象
    lineX: null, //  x 轴参考线
    lineY: null, // y 轴参考线

    drawStatus: false, // 当前的绘图状态  主要用处 鼠标点击下 到 鼠标松开的这个过程 （比如 矩形情况下 mousedown后移动 可以生成一个图形 多边形状态下 移动生成 多边形  拖拽状态下 移动整个图片）
    selectDomIsDraw: false, // 当前选中的图形是否可以拖拽 比如仅有  矩形框 和 多边形框 可以拖拽
    isClick: false, // 是否是点击事件
    isDrag: false, // 当前的拖拽
    isDragPoint: false, // 是否是拖动原点
    isOnPolyLine: false, // 当前鼠标是否在多边形上


    currentEndNearPoint: null, // 最近的结束点 （折线）
    currentStartNearPoint: null, // 最近的开始点 （折线）
    currentPoint: {
      x: 0,
      y: 0,
      rx: 0,
      ry: 0
    }, // 鼠标时时的点 （当前点）
    lastClickPoint: {
      x: 0,
      y: 0,
      rx: 0,
      ry: 0
    }, // 鼠标 mousedown 的坐标点
    comparePoint: {
      x: 0,
      y: 0,
      rx: 0,
      ry: 0
    }, // 鼠标 mouseup 的坐标点
    dragPoint: {
      x: 0,
      y: 0
    }, // 拖拽时的相对点
    mouseWheelPoint: {
      x: 0,
      y: 0,
      rx: 0,
      ry: 0
    }, // 滚轮事件的坐标
    selectPointId: '', // 当前选中的 需要移动的 SVG 图形上的点
    interimSelectId: '', //  临时选中的图形 id （mousedown 赋值  mouseup 清空） 为了确保当前 点下去的元素 和松开后的元素 是同一个
  }
};

// 整体初始化
OcrPublicClass.prototype.init = function () {
  // console.log($('.'+ that.vm.el));
  that.dm.draw = SVG(that.vm.el).size(that.vm.width, that.vm.height).attr({
    id: '_drawing'
  }); // 初始化
  that.dm.drawImg = that.dm.draw.image(that.vm.imgData.imgPath).loaded(function (loader) { // 加载图片 完成后的回调
    this.size(loader.width, loader.height).attr({
      id: 'svgImage'
    }); // 设置图片大小

    that.vm.imgData.width = loader.width; // 记录图片宽度
    that.vm.imgData.height = loader.height; // 记录图片高度
    that.dm.defaultGroup = that.dm.draw.group().attr({
      id: 'defaultGroup'
    }); // 创建一个组别，里面存储 img 和 标注属性 用来缩放等
    that.dm.lineX = createLine(1, '#f00', '5, 5', 'svg-cursor-x');
    that.dm.lineY = createLine(1, '#f00', '5, 5', 'svg-cursor-y');
    that.dm.defaultGroup.add(this); // 将图片放入
    that.dm.defaultGroup.add(that.dm.lineX); // 将 x 放入
    that.dm.defaultGroup.add(that.dm.lineY); // 将 y 放入

    createImgRect(loader, {
      // color: '#f00',
      // width: 3,
      // linecap: 'round',
      // dasharray: "20,10,5,5,5,10",
      // linejoin: 'miter'
    }); // 给最外层设置边框
    _setZoom(that.vm.el, 1); // 设置缩放比

    // 事件销毁
    that.destroyEvents();

    // 基础事件绑定
    that.addBaseEvent();

    // 判断是否禁用右键
    if (that.vm.isDisableRightKey) {
      document.oncontextmenu = function () {
        return false;
      }
    }

    // 图片加载后的回掉函数
    if (typeof that.vm.imgLoadCallBack === 'function') {
      that.vm.imgLoadCallBack();
    }
  });
};

// 事件绑定函数(支持业务代码自定义事件)
OcrPublicClass.prototype.bindEvents = function (event, func, isCustom) {
  if (isCustom) { // 如果是自定义事件，首先取消绑定事件
    that.dm.defaultGroup.off(event, func)
  }
  that.dm.defaultGroup.on(event, func.bind(that)) // 动态绑定 this 的指向
};

// 销毁当前 defaultGroup 上的事件
OcrPublicClass.prototype.destroyEvents = function (event) {
  if (event) {
    that.dm.defaultGroup.off(event);
  } else {
    that.dm.defaultGroup.off();
  }
};

// 添加基础绑定事件  不支持添加 齿轮事件
OcrPublicClass.prototype.addBaseEvent = function (type) {
  if (type === undefined) {
    that.bindEvents('mousemove', _svgToMouseMove, 0); // 移动事件
    that.bindEvents('mouseleave', _svgToMouseLeave, 0); // 离开事件
    that.bindEvents('mousedown', _svgToMouseDown, 0); // 点击的那一瞬间
    that.bindEvents('mouseup', _svgToMouseUp, 0); // 点击离开的瞬间
    agentFrom === 'Firefox' ? that.bindEvents('DOMMouseScroll', _svgMouseWheel, 0) : that.bindEvents('mousewheel', _svgMouseWheel, 0)
  } else { // 正则匹配 灵活处理
    // var funName = type.replace(/m|l|d|up|/g, function (e) {
    //   return e.slice(0, 1).toUpperCase() + e.slice(1)
    // });
    // funName = '_svgTo' + funName;
    var funName;
    if (type === 'mousedown') {
      funName = _svgToMouseDown
    } else if (type === 'mouseup') {
      funName = _svgToMouseUp
    } else if (type === 'mouseleave') {
      funName = _svgToMouseLeave
    } else if (type === 'mousemove') {
      funName = _svgToMouseMove
    }
    that.bindEvents(type, funName, 0);
  }
};

// 原型 返回当前时时的点坐标
OcrPublicClass.prototype.returnPoint = function (e) {
  var zoom = that.vm.zoom;
  if (agentFrom === 'Firefox') {
    return {
      x: e.layerX,
      y: e.layerY,
      rx: (e.layerX - that.vm.imgData.x) / zoom,
      ry: (e.layerY - that.vm.imgData.y) / zoom
    }
  } else {
    return {
      x: e.offsetX,
      y: e.offsetY,
      rx: (e.offsetX - that.vm.imgData.x) / zoom,
      ry: (e.offsetY - that.vm.imgData.y) / zoom
    }
  }
};

/**
 * 缩放函数 提供对外
 * @param zoom 缩放比例
 * @process ①设置缩放比例（双向绑定）② 重新渲染
 */
OcrPublicClass.prototype.setZoom = function (zoom, x, y) {
  if (!zoom) {
    zoom = that.vm.zoom;
  }
  _setData(zoom, x, y);
  _render()
};

/**
 * 设置缩放比例，居中变化
 * @param zoom 缩放比例
 */
OcrPublicClass.prototype.setZoomByCenter = function (zoom) {
  var data = that.getCenter(zoom),
    x = data.x || that.vm.imgData.x,
    y = data.y || that.vm.imgData.y;
  _setData(zoom, x, y);
  _render()
};

// 获取图形的相对中心
OcrPublicClass.prototype.getCenter = function (zoom) {

  // 校验
  if (zoom === that.vm.zoom) {
    return false;
  }

  var rx = that.vm.imgData.width / 2 || 0,
    ry = that.vm.imgData.height / 2 || 0, // 获取图形的相对中心
    dom = document.getElementById('svgImage'), // dom元素
    el = document.getElementById(that.vm.el), // 挂在的元素
    info, elInfo; // 元素信息

  if (dom && dom.nodeType === 1) { // 如果属于 DOM 元素
    elInfo = el.getBoundingClientRect(); // 获取挂载元素的信息
    info = dom.getBoundingClientRect(); // 获取image svg 元素信息
    var z_left = elInfo.left, // 最左边位置
      z_right = elInfo.right, // 最右边位置
      z_top = elInfo.top, // 最上边位置
      z_bottom = elInfo.bottom, // 最下面位置
      m_width = elInfo.width, // 图片最大计算宽度
      m_height = elInfo.height, // 最大计算高度
      top = info.top || 0, // 当前图片的 Top
      left = info.left || 0, // left
      right = info.right || 0, // right
      bottom = info.bottom || 0, // bottom
      height = info.height || 0, // height
      width = info.width || 0, // width
      cx, cy, x, // 图片偏移的x 相对坐标点不变
      y; // 图片偏移的y 相对坐标点不变

    if (left < z_left) { // 给图片位置一个零界点
      left = z_left + 1
    } else if (left > z_right) {
      left = z_right
    }

    if (right < z_left) { // 给图片位置一个零界点
      right = z_left + 1
    } else if (right > z_right) {
      right = z_right
    }

    if (bottom < z_top) { // 给图片位置一个零界点
      bottom = z_top + 1
    } else if (bottom > z_bottom) {
      bottom = z_bottom
    }


    if (top < z_top) { // 给图片位置一个零界点
      top = z_top + 1
    } else if (top > z_bottom) {
      top = z_bottom
    }

    left = left - z_left - 1; // 减去边框避免误差
    top = top - z_top - 1; // 减去边框避免误差
    right = right - z_left - 1; // 减去边框避免误差
    bottom = bottom - z_top - 1; // 减去边框避免误差

    if (width > m_width) { // 给图片宽度一个零界点
      width = m_width
    }

    if (height > m_height) { // 给图片高度一个零界点
      height = m_height
    }

    // cx = left + width / 2; // 旧版本
    // cy = top + height / 2; // 旧版本

    cx = left + (right - left) / 2; // 1.0 新版本
    cy = top + (bottom - top) / 2; // 1.0 新版本

    x = cx - ((cx - that.vm.imgData.x) / that.vm.zoom * zoom);
    y = cy - ((cy - that.vm.imgData.y) / that.vm.zoom * zoom);
    return {
      x: x,
      y: y
    };
  } else {
    warnInfo('can not find dom')
    return {
      x: 0,
      y: 0
    };
  }
};

/**
 * 矩形转多边形
 * @param id 元素id
 * @param func 回调函数
 */
OcrPublicClass.prototype.rectToPolygon = function (id, func) {
  var element = SVG.get(id),
    group = SVG.get(id + '-group'),
    rx, ry, w, h, arr, newElement;

  if (element.type !== 'rect') {
    return false;
  }

  rx = element.x();
  ry = element.y();
  w = element.width();
  h = element.height();
  arr = [
    [rx, ry],
    [rx + w, ry],
    [rx + w, ry + h],
    [rx, ry + h]
  ];

  // element.remove(); // 删除后，重新绘制
  group.remove();
  // SVG.get(id+'-text').attr({
  //     id: id.replace('r', 'p') + '-text',
  // });



  newElement = that.dm.defaultGroup.polygon(arr).attr({
    id: id.replace('r', 'p'),
    class: 'area-box',
    stroke: pColor,
    'stroke-width': that.vm.strokeWidth
  }).fill({
    color: pColor,
    opacity: '0.2'
  });
  _setDrawParent(id.replace('r', 'p'), '');
  _hidePoint(); // 隐藏所有的点

  if (typeof func === 'function') {
    func(newElement, id);
  }
};

/**
 * ①  将选择的图形置顶 ② 并且清空上一次绘制的点 ③ 根据当前图形的类别生成 不同的拖拽点
 * @param id
 * @constructor
 */
OcrPublicClass.prototype.createDragPoint = function (id) {
  var selectSVg = SVG.get(id);
  var selectBox = SVG.get(id + '-group');
  var groupLastChild = $('#defaultGroup').children('g:last')[0]; // 不要重复置顶  重复操作dom 影响单击事件
  // ① 置顶
  if (selectBox && selectBox.node !== groupLastChild) {
    selectBox.front(); // 置顶
  }
  console.log('被聚焦')
  // ② 清空
  _clearDrawPoint(); // 清空绘制的原点
  _clearHightlight(); // 去除所有高亮
  // ③ 生成
  if (/^r-\d+/g.test(id)) { // 矩形
    _createRecPoint(selectSVg)
  } else if (/^p-\d+/g.test(id)) {
    _createPolyPoint(selectSVg)
  } else if (/^pl-\d+/g.test(id)) {
    _createPolyLinePoint(selectSVg)
  } else if (/^opl-\d+/g.test(id)) {
    _createPolyPoint(selectSVg)
  } else if (/^copl-\d+/g.test(id)) {
    _createPolyPoint(selectSVg)
  }
};

/**
 * 清空之前绘制的拖拽点
 * @private
 * @process 循环遍历移除 生成的点
 */
OcrPublicClass.prototype.clearDrawPoint = function () {
  var lastAdjustSizeBox = SVG.select('.adjust-size');
  lastAdjustSizeBox.each(function () {
    this.remove();
  });
};
/**
 * 移出页面上的所有高亮
 * @private
 * @process
 */
OcrPublicClass.prototype.clearHightlight = function () {
  SVG.select('.' + that.vm.svgHightLightClass).removeClass(that.vm.svgHightLightClass);
  // console.log('移出高亮',SVG.select(that.vm.svgHightLightClass));
}

/**
 * 添加高亮
 * @private
 * @process
 */
OcrPublicClass.prototype.addHightlight = function (id) {
  if (id !== 'defaultGroup') {
    SVG.get(id).addClass(that.vm.svgHightLightClass);
  }

}
/**
 * 初始化十字光标
 */
OcrPublicClass.prototype.initCursor = function () {
  that.dm.lineX.front().plot(0, 0, 0, 0);
  that.dm.lineY.front().plot(0, 0, 0, 0);
};

/**
 * 多边形点撤回
 * @param e
 * @returns {boolean}
 */
OcrPublicClass.prototype.revokePolygon = function (e) {
  var currentDraw = that.dm.currentDraw, // 当前绘制的实例
    type = that.vm.type,
    points, rx, ry; // 需要绘制的点

  if (!currentDraw) { // 如果不存在
    return false;
  } else {
    if (type === 'polygon') {
      points = currentDraw.array().value.slice(0);
      points.splice(-1);
      currentDraw.plot(points);
      rx = that.dm.currentPoint.rx; // 相对 x 的位置
      ry = that.dm.currentPoint.ry; // 相对 y 的位置
      points.splice(-1, 1, [rx, ry]);
      currentDraw.plot(points);

      _revokeCheck(currentDraw);
    }
  }
};

/**
 * 修改 isOnPolyLine 状态
 * @param status
 * @constructor
 */
OcrPublicClass.prototype.ChangeOnPolyLine = function (status) {
  that.dm.isOnPolyLine = status;
};

/**
 * 多边形绑定事件
 */
OcrPublicClass.prototype.bindPolygon = function (type) {
  var lastClickPoint = that.dm.lastClickPoint,
    currentPoint = that.dm.currentPoint;
  if (type === 'mouseleave') {
    that.dm.isOnPolyLine = false;
    if (lastClickPoint.rx === currentPoint.rx && lastClickPoint.ry === currentPoint.ry) { // 点的坐标没有移动触发了 移动事件
      warnInfo('点击事件触发了多边形移动事件');
      return false;
    }
    __svgToMoveLeaveByPolygon();
  } else if (type === 'mousemove') {
    that.dm.isOnPolyLine = true;
  }
};

/**
 * 折线选中
 */
/**
 * 折线选中 choosePolyLine
 */
//OcrPublicClass.prototype.choosePolyLine = function (id, className) {
function choosePolyLine(id, className) {
  if (that.vm.type !== 'click') { // 类型判断
    return;
  }
  var curPointY = that.dm.comparePoint.ry,
    // 所有折线
    pl = SVG.select('.' + id + '-polyline').members,
    minY = 0,
    plY = [];

  // 选中的多边形内的折线第一个点的Y坐标
  for (var i = 0; i < pl.length; i++) {
    plY.push({
      y: pl[i]._array.value[0][1],
      id: pl[i].node.id
    });
  }

  plY.sort(function (a, b) {
    return a.y - b.y
  });

  for (var i = 0; i < plY.length; i++) {
    if (plY[i].y - curPointY > 0) {
      if (minY === 0) {
        minY = plY[i]
      } else if (minY > 0 && plY[i].y < min) {
        minY = plY[i]
      }
    }
  }

  // console.log('choose',id, className ,minY.id ,SVG.get(minY.id) && plY[0] !== minY)
  if (SVG.get(minY.id) && plY[0] !== minY) {
    // that.createDragPoint(minY.id)
    // _addHightlight(minY.id)
    return minY.id
  } else if (SVG.get(minY.id) && plY[0] === minY) {
    return {
      name: 'firstLine',
      id: minY.id
    }
  }
};

/**
 * 根据缩放比例设置‘
 * @param element
 */
OcrPublicClass.prototype.allChangeByZoom = function (element) {
  try {
    element.each(function (i, children) {
      var type = this.type,
        zoom = that.vm.zoom,
        strokeWidth = that.vm.strokeWidth,
        dragPointSize = that.vm.dragPointSize,
        width = 2,
        circleWidth = 10;
      if (type === 'g') {
        that.allChangeByZoom(this);
      } else if (type !== 'g' && this.type !== 'circle') {
        width = strokeWidth / zoom;
        if (width > strokeWidth) {
          width = strokeWidth;
        }
        this.stroke({
          width: width
        })
      } else if (type === 'circle') {
        circleWidth = dragPointSize / zoom;
        if (circleWidth > dragPointSize) {
          circleWidth = dragPointSize;
        }
        this.size(circleWidth)
      }
    })
  } catch (e) {
    warnInfo(e);
  }

};

// 显示隐藏图形的文本内容
// id 和 txt 都为空时  全部显示隐藏
// 仅id存在  需要显示隐藏的 id
//  id 和 text 同时存在  修改id的文本内容
//  不支持 txt  存在 id 不存在  的情况
// isShow 是否显示
OcrPublicClass.prototype.showText = function (isShow, id, txt) {
  // console.log(SVG.get(id).node.style);
  if (id) {
    var text = $('#' + id + '-text'); // .siblings('text');
    if (txt) {
      text.find('tspan').html(txt);
      // return;
    }
    if (isShow) {
      text.css('display', 'block')
    } else {
      text.css('display', 'none')
    }
  } else {
    if (isShow) {
      $('text').css('display', 'block')
    } else {
      $('text').css('display', 'none')
    }
  }
}


/**
 * 根据数据绘制图形
 * @param list
 */
OcrPublicClass.prototype.drawByListData = function (list) {
  // console.log('绘制list',list)
  var dataType = Object.prototype.toString.call(list);

  if (dataType === '[object Object]') { // 对象
    for (var i in list) {
      if (list[i].region === 'area') { // 绘制多边形
        _markPolygon(list[i]);
      } else if (list[i].region === 'rect') { // 绘制矩形
        _markRect(list[i]);
      } else if (list[i].region === 'polyline') { // 绘制折线
        _markPolyLine(list[i]);
        // console.log('绘制折线 11');
      } else if (list[i].region === 'closeOverPolyline') {
        _markCloseOverPolyline(list[i])
      }
    }
  } else if (dataType === '[object Array]') { // 数组
    for (var j = 0, len = list.length; j < len; j++) {
      // console.log('绘制图形',list[j].region)
      if (list[j].region === 'area') { // 绘制多边形
        // console.log('绘制矩形 11111');
        _markPolygon(list[j]);
      } else if (list[j].region === 'rect') { // 绘制矩形
        _markRect(list[j]);
      } else if (list[j].region === 'polyline') { // 绘制折线
        // console.log('绘制折线 22');
        _markPolyLine(list[j]);
      } else if (list[j].region === 'closeOverPolyline') {
        _markCloseOverPolyline(list[j])
      }

      if (list[j].children && list[j].children.length > 0) { // 如果有子元素，且长度大于0
        that.drawByListData(list[j].children)
      }
    }
  }
};

/**
 * 对外的图片拖拽
 * @param e
 */
OcrPublicClass.prototype.svgToMoveDrag = function (e) {

  var dragPoint = that.dm.lastClickPoint,
    currentPoint = that.dm.currentPoint;

  that.vm.imgData.x = that.vm.imgData.x + currentPoint.x - dragPoint.x;
  that.vm.imgData.y = that.vm.imgData.y + currentPoint.y - dragPoint.y;
  _render();

  _getPoint(e, 1); // 获取上次点击的坐标
};

/**
 * 获取点的坐标  优化实现方式  合并在一起
 * @param e
 * @param type 0 获取时时点的坐标 1 获取 mousedown 时点的坐标  2 获取 mouseup 时点的坐标
 * @private
 */
OcrPublicClass.prototype.getPoint = function (e, type) {
  var zoom = that.vm.zoom;
  var name = type === 0 ? 'currentPoint' : (type === 1 ? 'lastClickPoint' : 'comparePoint');
  var x = 0,
    y = 0;
  if (agentFrom === 'Firefox') {
    x = e.layerX;
    y = e.layerY;
    that.dm[name].x = e.layerX; // 相对可视区域
    that.dm[name].y = e.layerY; // 相对可视区域
  } else {
    x = e.offsetX;
    y = e.offsetY;
    that.dm[name].x = e.offsetX; // 相对可视区域
    that.dm[name].y = e.offsetY; // 相对可视区域
  }

  if (that.vm.rotateDeg === 1) { // 旋转0°
    that.dm[name].rx = (x - that.vm.imgData.x) / zoom; // 理论上相对 defaultgroup的位置 (也就是说 当前鼠标位置 减去 当前图片所处的位置，处于缩放比例就是当前相对位置)
    that.dm[name].ry = (y - that.vm.imgData.y) / zoom // 理论上相对 defaultgroup的位置  
  } else if (that.vm.rotateDeg === 2) { // 旋转90°
    that.dm[name].rx = (y - that.vm.imgData.y) / zoom; // 理论上相对 defaultgroup的位置 (也就是说 当前鼠标位置 减去 当前图片所处的位置，处于缩放比例就是当前相对位置)
    that.dm[name].ry = -(x - that.vm.imgData.x) / zoom // 理论上相对 defaultgroup的位置
  } else if (that.vm.rotateDeg === 3) {
    that.dm[name].rx = -(x - that.vm.imgData.x) / zoom; // 理论上相对 defaultgroup的位置 (也就是说 当前鼠标位置 减去 当前图片所处的位置，处于缩放比例就是当前相对位置)
    that.dm[name].ry = $('#defaultGroup').height() - (y - that.vm.imgData.y) / zoom // 理论上相对 defaultgroup的位置
  } else if (that.vm.rotateDeg === 4) {
    that.dm[name].rx = -(y - that.vm.imgData.y) / zoom; // 理论上相对 defaultgroup的位置 (也就是说 当前鼠标位置 减去 当前图片所处的位置，处于缩放比例就是当前相对位置)
    that.dm[name].ry = (x - that.vm.imgData.x) / zoom; // 理论上相对 defaultgroup的位置
  }
};

/**
 * 初始化mouseWheelPoint 点
 */
OcrPublicClass.prototype.initWheelPoint = function () {
  that.dm.mouseWheelPoint = {
    x: 0,
    y: 0,
    rx: 0,
    ry: 0
  };
};

/**
 * 取消绘图，可以理解为删除当前图形
 */
OcrPublicClass.prototype.cancelDraw = function (id) {
  if (id) { // 如果外面有id

  } else {
    var currentDraw = that.dm.currentDraw;
    if (!currentDraw) { // 无绘图实例
      $('.nearPoint').remove(); // 分行线取消绘制 两个端点
      $('.horizonLine').remove(); // 分行线的两条参考下
      return false;
    } else {
      currentDraw.remove();
      $('.nearPoint').remove(); // 分行线取消绘制 两个端点
      $('.horizonLine').remove(); // 分行线的两条参考下
      _initCursor(); // 初始化光标
      _initDrawStatus(); // 初始化绘制状态
    }
  }
};

/**
 * 对外的图形校验
 */
OcrPublicClass.prototype.externalCheck = function () {
  _initCursor(); // 初始化光标
  _checkCurrentDraw(); // 校验是否符合标准
  _initDrawStatus(); // 初始化绘制状态
  _errorHandle(); // 非正常情况处理
}

/**
 * 2018/11/6 纯粹为了业务弥补欠缺
 * @param e
 * @param id
 */
OcrPublicClass.prototype.setPointbPoint = function (e, id) {
  // _getPoint(e, 0);
  var currentPoint = that.dm.currentPoint;
  that.dm.selectPointId = id;
  that.dm.isDragPoint = true; // 当前是否可以拖拽
  that.dm.selectPointId = id; // 当前选择的 拖拽点
  SVG.get(id).data("bPoint", {
    bx: currentPoint.rx,
    by: currentPoint.ry
  });
  // console.log(SVG.get(id),currentPoint,99999999999999)
  SVG.get(id).addClass('active');
  SVG.get(id).off('mouseup');
  var parentId = SVG.get(id).data('parent')
  SVG.get(id).on('mouseup', function () {
    that.createDragPoint(parentId); // 图形被聚焦
    that.addHightlight(parentId);
  })
}


// 对外设置光标   
OcrPublicClass.prototype.setCursor = function () {
  var graphY = that.dm.currentPoint.ry,
    graphX = that.dm.currentPoint.rx,
    type = that.vm.type,
    selectId = that.vm.selectId,
    point, currentSelectObject;

  if (type === 'polyline' || type === 'closeOverPolyline') {
    currentSelectObject = SVG.get(selectId);
    point = [graphX, graphY + 2]; // point
    _drawHorizon(currentSelectObject, point, point)
  } else {
    that.dm.lineX.front().plot(0, graphY + 1, that.dm.drawImg.width(), graphY + 1);
    that.dm.lineY.front().plot(graphX + 1, 0, graphX + 1, that.dm.drawImg.height());
  }
}
////////////////////////////////////////////////////////////////////
// 工具函数  内部函数
//////////////////////////////////////////////////////////////////

/**
 * 初始化绘制多边形
 * @param data
 * @private
 */
function _markPolygon(data) {
  // console.log('绘制矩形',11234)
  var initPolyDom = that.dm.defaultGroup.polygon(data.points).attr({
    id: data.id,
    class: 'area-box',
    stroke: pColor,
    'stroke-width': that.vm.strokeWidth
  }).fill({
    color: pColor,
    opacity: 0
  });
  _setDrawParent(data.id) // 给当前绘制的图形增加一个父亲 group
}



/**
 * 初始化 绘制矩形
 * 内部 根据数据绘制矩形
 * @private
 */
function _markRect(data) {
  var h = data.h,
    w = data.w,
    x = data.x,
    y = data.y,
    id = data.id;
  that.dm.defaultGroup.rect(w, h).move(x, y).fill({
    color: rColor,
    opacity: 0
  }).attr({
    id: id,
    class: 'area-box'
  }).stroke({
    color: rColor,
    width: that.vm.strokeWidth,
    linecap: 'round',
    linejoin: 'miter'
  });
  _setDrawParent(data.id) // 给当前绘制的图形增加一个父亲 group
}

/**
 * 初始化 绘制折线
 * 内部折线绘制
 * @param data
 * @private
 */
function _markPolyLine(data) {
  that.dm.defaultGroup.polyline(data.points).attr({
    id: data.id,
    class: 'area-box ' + data.pId + '-polyline',
    stroke: plColor,
    'stroke-width': that.vm.strokeWidth
  }).fill({
    color: plColor,
    opacity: '0'
  }).data('parent', data.pId);
  // console.log('绘制折线',data.pId);
  _setPolyLineParent(data.id, data.pId);
}



/**
 * 初始化 绘制闭合折线
 *  单独闭合折线绘制 (是否存在实例)
 * @private
 */
function _markCloseOverPolyline(data) {

  // 折线绘制
  that.dm.defaultGroup.polyline(data.points).attr({
    id: data.id,
    class: 'area-box ' + data.id + '-polyline copl-polyline',
    stroke: 'red',
    'stroke-width': that.vm.strokeWidth,
  }).fill({
    color: '#3656bf',
    opacity: '0'
  }).data({
    parent: data.id
  });
  _setDrawParent(data.id);
}





/**
 * 给折线绘制group
 * @param id 自己的id
 * @param parent 自己父亲的id
 * @private
 */

function _setPolyLineParent(id, parent) {
  var svgNode = SVG.get(id),
    groupId = parent + '-group',
    parentGroup = SVG.get(groupId);
  // console.log('_setPolyLineParent',id,svgNode)
  // parentGroup = that.dm.defaultGroup.group().attr({id: groupId, class: 'area-box-group'});
  parentGroup.add(svgNode);
  _setTextByDraw(svgNode, parentGroup, id);
}

/**
 * 多边形离开问题
 */
function __svgToMoveLeaveByPolygon() {
  var type = that.vm.type,
    isDragPoint = that.dm.isDragPoint,
    parentId;
  try {
    parentId = SVG.get(that.dm.selectPointId).data('parent')
  } catch (e) {
    parentId = ''
  }

  if (type === 'polyline' || (type === 'click' && isDragPoint && /^pl-\d+/g.test(parentId))) { // 线段的时候 (有个bug) 利用查找父元素的id
    // console.log('是否离开')
    _checkCurrentDraw(); // 校验是否符合标准
    _initDrawStatus(); // 初始化绘制状态
    // console.log(1111111111111)
  }
}

/**
 * 撤销检查
 * @param currentDraw
 * @private
 */
function _revokeCheck(currentDraw) {
  var len = currentDraw.array().value.length;
  if (len < 3) {
    currentDraw.remove();
    _initDrawStatus(); // 需要清除绘图
    // console.log(2222222222222)
  }
}

/**
 * 内部生成 矩形拖拽点
 * @param data SVG 图形实例对象
 * @private
 * @process 获取矩形宽 高 以及四个点 坐标。每个点的坐标 记录 对角点的位置
 */
function _createRecPoint(data) {
  var x = data.x(),
    y = data.y(),
    width = data.width(),
    height = data.height(),
    pointArr = [],
    diagonalPoints = [],
    leftTop = [x, y],
    leftBottom = [x, y + height],
    rightTop = [x + width, y],
    rightBottom = [x + width, y + height],
    parent = data.id(); // 获取归属于 哪一个图形
  pointArr = [leftTop, leftBottom, rightTop, rightBottom];
  diagonalPoints = [rightBottom, rightTop, leftBottom, leftTop];
  _createSpecificPoint(pointArr, 'rect', parent, diagonalPoints)
}

/**
 * 内部生成 多边形拖拽点
 * @param data SVG 图形 实例对象
 * @private
 * @process 获取矩形坐标点
 */
function _createPolyPoint(data) {
  var point = data.array().value,
    parent = data.id(); // 获取归属于 哪一个图形
  _createSpecificPoint(point, 'polygon', parent)
}

/**
 *  内部生成 折线拖拽点
 */
function _createPolyLinePoint(data) {
  var point = data.array().value,
    parent = data.id(); // 获取归属于 哪一个图形
  _createSpecificPoint(point, 'polyline', parent)
}

/**
 * 生成 点坐标
 * @param info
 * @param type
 * @param parent
 * @param diagonalPoints
 * @private
 */
function _createSpecificPoint(info, type, parent, diagonalPoints) {
  var dragPointSize = that.vm.dragPointSize, // 固定控制点大小
    zoom = that.vm.zoom,
    svgImg = document.getElementById('svgImage'),
    svgImgW = svgImg.getBoundingClientRect().width;
  var currentPoint = that.dm.currentPoint,
    i, point, parentId;
  if (svgImgW < 180) {
    dragPointSize = 30;
  } else {
    dragPointSize = dragPointSize / zoom;
  }
  var halfDragPointSize = dragPointSize / 2;
  // 循环生成点
  for (i = 0; i < info.length; i++) {
    point = that.dm.defaultGroup.circle(dragPointSize).move(info[i][0] - halfDragPointSize, info[i][1] - halfDragPointSize).attr({
        id: 'point' + i,
        class: 'adjust-size'
      })
      .fill({
        color: '#00a2ff',
        opacity: '0.9'
      }).data({
        parent: parent,
        minePoint: [info[i][0], info[i][1]],
        'point-index': i
      })
    // .stroke({color: '#9dc1ff', width: that.vm.strokeWidth, linecap: 'round', linejoin: 'miter'}).data('parent', parent);


    // console.log(type,12133);
    if (type === 'polyline') {
      parentId = SVG.get(parent).data('parent') + '-group';
      SVG.get(parentId).add(point);
    }

    if (type === 'rect') {
      point.data('diagonalPoints', diagonalPoints[i])
    }

    point.off('mousedown'); // 销毁事件
    point.off('mouseover'); // 销毁事件
    point.off('mouseout'); // 销毁事件
    // 给这些点 绑定事件
    point.on('mousedown', function (e) {
      _getPoint(e, 0); // 2018/11/6 增加 解决bug, 暂未定位到问题所在
      var id = e.target.id;
      that.dm.isDragPoint = true; // 当前是否可以拖拽
      that.dm.selectPointId = id; // 当前选择的 拖拽点
      SVG.get(id).data("bPoint", {
        bx: that.dm.currentPoint.rx,
        by: that.dm.currentPoint.ry
      });

      if (e.button == 0) {
        SVG.get(id).addClass('active');
      }
      if (typeof that.vm.pointMouseDown === 'function') {
        that.vm.pointMouseDown(id);
      }
    });
    point.on('mouseover', function () {
      this.size(that.vm.dragPointSize / that.vm.zoom * 1.6).attr({
        'stroke-width': 2 / that.vm.zoom
      })
    })
    point.on('mouseout', function () {
      var svgImg = document.getElementById('svgImage');
      svgImgW = svgImg.getBoundingClientRect().width;
      var adjustSize = '';
      if (svgImgW < 180) {
        adjustSize = 30;
      } else {
        adjustSize = that.vm.dragPointSize / that.vm.zoom;
      }
      this.size(adjustSize).attr({
        'stroke-width': 0
      })
    })
    point.on('contextmenu', function (e) {
      e.stopPropagation();
      e.preventDefault();
      // this.removeClass('active');
      if (typeof that.vm.pointContextmenuCallback === 'function') { // 修改图形后，可能存在回调函数
        that.vm.pointContextmenuCallback(e, this);
      }
    })
  }
}


/**
 * 清空之前绘制的拖拽点
 * @private
 * @process 循环遍历移除 生成的点
 */
function _clearDrawPoint() {
  var lastAdjustSizeBox = SVG.select('.adjust-size');
  lastAdjustSizeBox.each(function () {
    this.remove();
  });
}

/**
 * 移出页面上的所有高亮
 * @private
 * @process
 */
function _clearHightlight(id) {
  if (id) {
    SVG.get(id).removeClass(that.vm.svgHightLightClass);
  } else {
    SVG.select('.' + that.vm.svgHightLightClass).removeClass(that.vm.svgHightLightClass);
  }
  // console.log('移出高亮',SVG.select(that.vm.svgHightLightClass));
}

/**
 * 添加高亮
 * @private
 * @process
 */
function _addHightlight(id) {
  if (id !== 'defaultGroup') {
    SVG.get(id).addClass(that.vm.c);
  }

}

/**
 * mouseWheel 事件
 * @private
 */
function _svgMouseWheel(e) {
  var changeZoom = 1,
    x = 0,
    y = 0,
    type = that.vm.type;
  if (e.detail) {
    changeZoom = -(e.detail / 60);
  } else if (e.wheelDelta) {
    changeZoom = (e.wheelDelta / 4800);
  }

  if (that.dm.mouseWheelPoint.x === 0 && that.dm.mouseWheelPoint.y === 0 &&
    that.dm.mouseWheelPoint.rx === 0 && that.dm.mouseWheelPoint.ry === 0) {
    _getPoint.bind(that, e, 0); // 获取当前相对坐标点
    that.dm.mouseWheelPoint = that.returnPoint(e); // 获取滑轮瞬间的坐标点
  } // 获取到当前的点

  that.vm.zoom += changeZoom;
  if (that.vm.zoom > that.vm.maxZoom) { // 获取当前的缩放比例
    that.vm.zoom = that.vm.maxZoom
  } else if (that.vm.zoom < that.vm.minZoom) {
    that.vm.zoom = that.vm.minZoom
  }

  if (agentFrom !== 'Firefox') { // 非火狐
    x = e.offsetX - (that.dm.mouseWheelPoint.rx * that.vm.zoom); // 图片偏移的x 相对坐标点不变
    y = e.offsetY - (that.dm.mouseWheelPoint.ry * that.vm.zoom); // 图片偏移的y 相对坐标点不变
  } else {
    x = e.layerX - (that.dm.mouseWheelPoint.rx * that.vm.zoom); // 图片偏移的x 相对坐标点不变
    y = e.layerY - (that.dm.mouseWheelPoint.ry * that.vm.zoom); // 图片偏移的y 相对坐标点不变
  }

  that.setZoom(that.vm.zoom, x, y); // 设置
  changeStrokeByZoom(that.dm.defaultGroup);
  if (type === 'rect' || type === 'polygon' || type === 'polyline') {
    _getPoint.bind(that, e, 0); // 获取坐标时时的点
    _setCursor(e); // 设置十字光标的位置
  }
}

/**
 * 初始化滚轮参数
 * @private
 */
function _initWheelPoint() {
  that.dm.mouseWheelPoint = {
    x: 0,
    y: 0,
    rx: 0,
    ry: 0
  };
}

/**
 * mouseDown 事件
 * 思考鼠标左击 可能有哪些事件 ① 可能是click也可能不是click （因此需要初始化一个参数来代表是否是click）② 可能是绘制图形 （考虑到鼠标移动 绘制图形,需要增加一个参数来表示绘制状态）
 * ③ 也可能是拖拽 等
 * ④ 增加一个临时的 元素id ，用来对比 mouseup 是否是同一个元素
 * @private
 * @flow  1. mouseDown 分为 左键点击事件 和  右键点击事件
 * 2. 鼠标左键 点击时 需要记录 ① currentPoint ② lastClickPoint ③
 */
function _svgToMouseDown(e) {
  // e.stopPropagation(); // 阻止冒泡
  // e.preventDefault(); // 防止浏览器默认事件
  if (e.button === 0) { // 左键
    var type = that.vm.type, // 当前是什么类型
      id = e.target.id; // 当前选中的id

    _getPoint.call(that, e, 0); // 获取 currentPoint 时时
    _getPoint.call(that, e, 1); // 获取 lastClickPoint 点击
    _initDataByMouseDown(e); //  初始化必要的参数

    if (type === 'polygon') { // 多边形在 mouseDown 即可以绘制
      _svgToDrawPolygon.call(that);
    } else if (type === 'drag') { // 拖拽状态时 初始化 拖拽状态
      that.dm.isDrag = true;
    } else if (type === 'click') { // 当前是点击状态  需要判断 选择的图形是否可以拖拽 和整体拖拽 不同
      _judgeIsDraw(id);
    } else if (type === 'polyline') { // 多边形中的折线绘制
      _svgToDrawPolyLine();
    } else if (type === 'overPolyline') { // 不闭合折线绘制
      _svgToDrawOverPolyLine();
    } else if (type === 'closeOverPolyline') { // 两端点与画布相交折线
      _svgToDrawCloseOverPolyLine();
    }
    // else if( type === 'rect'){
    //   if(that.dm.currentDraw){
    //     _checkCurrentDraw(); // 校验图形，结束绘图
    //     _initDrawStatus(); // 结束绘图    
    //   }
    // }

  } else if (e.button === 2) { // 鼠标右键  结束绘图
    _checkCurrentDraw(); // 绘图结束，校验图形
    _initDrawStatus(e); // 初始化绘制状态
    // console.log(33333333333333)
  }
}

/**
 * 判断点的元素是否可拖拽
 * @param id
 * @private
 */
function _judgeIsDraw(id) {
  if (/^r-\d+|^p-\d|^opl-\d|^copl-\d/g.test(id)) {
    that.dm.selectDomIsDraw = true; // 初始化图形 是否可移动的属性 主要是区分最外层的svg 图形
    SVG.get(id).data('selectPoint', {
      rx: that.dm.lastClickPoint.rx,
      ry: that.dm.lastClickPoint.ry
    }) // 给点击的图形设置点击点 的坐标点 ， 方便移动时的计算
  } else {
    id = 'defaultGroup';
    that.vm.SelectDomoIsDraw = false;
    SVG.get(id).data('selectPoint', {
      rx: that.dm.lastClickPoint.rx,
      ry: that.dm.lastClickPoint.ry
    }) // 给点击的图形设置点击点 的坐标点 ， 方便移动时的计算
  }
}

/**
 * mouseDown的是否需要初始化的参数
 * @private
 */
function _initDataByMouseDown(e) {
  that.dm.isClick = false; // 初始化点击参数 初始化为 false 因为 单次点击无法确认是否 执行click
  that.dm.drawStatus = true; // 初始化 是否可以绘制的状态  初始化为 true 因为 单次点击 即可 执行绘制过程 (也可理解为 当前一直在 左击状态)
  that.dm.interimSelectId = e.target.id; // 初始化临时点击元素参数 记录一下 临时id 因为需要 确定松开后 是否在同一元素上
}

/**
 * mouseLeave 事件
 * @private
 *
 */
function _svgToMouseLeave() {
  var lastClickPoint = that.dm.lastClickPoint,
    currentPoint = that.dm.currentPoint;

  if (lastClickPoint.rx === currentPoint.rx && lastClickPoint.ry === currentPoint.ry) { // 点的坐标没有移动触发了 移动事件
    warnInfo('点击事件触发了移动事件');
    return false;
  }

  if (that.vm.leaveEnd) { // 根据业务参数配置
    _initCursor(); // 初始化光标
    _checkCurrentDraw(); // 校验是否符合标准
    _initDrawStatus(); // 初始化绘制状态
    _errorHandle(); // 非正常情况处理
  }

}

/**
 * 一些特殊情况的 兼容性处理  此时主要是 在图形外部移动时，可能导致的问题
 * @private
 */
function _errorHandle() {
  var type = that.vm.type; // 类型
  if (type === 'rect') {
    _checkCurrentDraw();
  } else if (type === 'click') { // 此时可能 移动点的坐标过快导致
    that.dm.SelectDomIsDraw = false; // 取消拖拽状态
    that.dm.isDragPoint = false; // 初始化 点的状态
    that.dm.interimSelectId = ''; // 清空临时选择id
  } else if (type === 'drag') {
    // alert(3)
    that.dm.isDrag = false; // 当前不可拖拽
  }
  _initDrawStatus();
  // console.log(555555555555555)
  return false;
}

/**
 * mousemove 事件
 * 思考鼠标移动过程具体有哪些操作 1. 十字光标，当且仅当绘图时才会出现（多边形，矩形等） 2. 获取点的坐标  3. 初始化滚轮参数
 * 更深层次的 图形绘制！！！以及拖拽等！！！
 * @private
 */
function _svgToMouseMove(e) {
  var type = that.vm.type;
  _getPoint.call(that, e, 0); // 获取时时点
  _initWheelPoint(); // 初始化 齿轮 WheelPoint 参数
  _svgToMoveHandle.call(that, e); // 鼠标移动的主要逻辑部分
  if (type == 'closeOverPolyline') {
    that.vm.selectId = 'image-border';
  }
  if (types.indexOf(type) !== -1) { // 当前类型 是否存在于 绘图类型库？
    _setCursor.call(that, e);
  }
}

/**
 * mouseup 事件
 * 思考当松开时有哪些操作 1. 矩形时 结束绘图 （是否这种处理方式）2. 拖拽时 结束拖拽  3. 移动时 结束移动 4. 判断是否是点击事件（前后坐标对比）
 * 1.记录 mouseup的点
 * 2.矩形状态下 结束绘图状态
 * 3.点击状态下 初始化可拖拽的状态 false 初始化可拖拽的点 false
 * 4.移动状态下 初始化可drag的状态 false
 * @private
 */
function _svgToMouseUp(e) {
  // e.stopPropagation(); // 阻止冒泡
  // e.preventDefault(); // 防止浏览器默认事件
  _getPoint.call(that, e, 2); // 获取松开的点
  var type = that.vm.type, // 绘制类型
    comparePoint = that.dm.comparePoint, // mouseup的点
    clickPoint = that.dm.lastClickPoint, // mousedown的点
    interimSelectId = that.dm.interimSelectId, // 临时 Id
    eventId = e.target.id; // 当前id
  // 判断是否是点击事件
  if (comparePoint.x === clickPoint.x && comparePoint.y === clickPoint.y &&
    comparePoint.rx === clickPoint.rx && comparePoint.ry === clickPoint.ry) {
    that.dm.isClick = true;
    _svgClick(e, 1); // 触发点击函数 点相同
  } else if (interimSelectId === eventId && type === 'click') { // 由于业务原因,如果当前图形属于同一个元素，也认为是点击事件
    that.dm.isClick = true;
    _svgClick(e, 1); // 触发点击函数 点不相同 （由于目前没有细分，暂时传1）
  } else if (eventId === 'svgImage' && /^p-\d+/g.test(SVG.get(interimSelectId).data('parent')) && type === 'click') { // 鼠标移动过快 移出拖拽点范围 导致mousedown和mouseup的id不同
    that.dm.isClick = true;
    _svgClick(SVG.get(interimSelectId).data('parent'), 1); // 触发点击函数 点不相同 （由于目前没有细分，暂时传1）
  }

  // 主要逻辑处理
  // 更换矩形绘制方式 两点绘制一个矩形
  // if (type === 'rect') { // 矩形
  //   _checkCurrentDraw(); // 校验图形，结束绘图
  //   _initDrawStatus(); // 结束绘图
  // } else 
  if (type === 'click') { // 点击
    _initClickStatus(); // mouseup && click 时 需要初始化参数
    _initDrawStatus();
  } else if (type === 'drag') { // 拖拽
    _initDragStatus(); // 初始化拖拽状态
    _initDrawStatus();
  }
}

/**
 * 点击事件 type 暂时预留 （可能点击事件，也可能需要点击为同一元素上）
 * type 1 mousedown mouseup 点相等
 * type 2 mousedown mouseup 不相等 ，但是都在同一元素上
 * @private
 */
function _svgClick(e, type) {
  var id = 'defaultGroup', // 默认id
    targetId = typeof e === 'string' ? e : e.target.id, // 目标元素id
    targetType = that.vm.type, // 绘图类型
    isHide;
  if (/^r-\d+|^p-\d+|^opl-\d+|^copl-\d+/g.test(targetId)) { // 来确定当前选择的图形
    id = targetId
  } else if (/^point\d+/g.test(targetId)) {
    id = SVG.get(targetId).data('parent')
  } else if (/^pl-\d+/g.test(targetId)) { // 来确定当前的绘制的元素
    id = targetId;
    isHide = true;
    id = SVG.get(id).parent().node.childNodes[0].id;
  } else if (/^horizonLine-/g.test(targetId)) { // 如果是水平线 （临时存在的，不应该做任何处理）
    return; // id = targetId;  // isHide = true; // id = SVG.get(id).attr('parentId');
  } else if (/^overPoint/g.test(targetId)) { // 如果是绘制折线时与多边形的焦点 （临时存在的，不应该做任何处理）
    return;
  }


  if (targetType === 'polyline' && id === 'defaultGroup') { // 为了解决在多边形外绘图的bug (不能根据isOnPolyLine 判断会有匪夷所思的bug)
    return
  }

  if (/^pl-\d+|^p-\d+/g.test(id) && that.vm.canChooseP || id === 'defaultGroup' || /^copl-\d+/g.test(id)) {
    that.dm.isOnPolyLine = true;
    var copeId = '';
    id == 'defaultGroup' || /^copl-\d+/g.test(id) ? copeId = 'copl' : copeId = id;
    var chooseId = choosePolyLine(copeId, that.vm.svgHightLightClass);
    // console.log(chooseId)
    // id = chooseId != undefined ? chooseId : 'defaultGroup'
    if (typeof chooseId === 'string') {
      id = chooseId;
    } else if (typeof chooseId === 'object' && that.vm.lastLineIsOpera === true) {
      id = chooseId.id
    }
  }

  // 虽然是业务参数，但是构造函数中，必用所以在这里赋值了
  // that.vm.selectId = id;
  if (typeof (that.vm.clickCallBack) === 'function' && that.vm.type === 'click' && type === 1) { // 点击事件对应的回调函数

    that.vm.clickCallBack(id, isHide, e); // isHide 折线参数
  }
}

/**
 * 初始拖拽状态
 * @private
 */
function _initDragStatus() {
  // alert(2)
  that.dm.isDrag = false; // 当前不可拖拽
}

/**
 * 初始化绘图状态
 * @private
 */
function _initDrawStatus() {
  // console.log("asdasdasdadasdsadsad")
  that.dm.drawStatus = false; // 绘图状态必然结束 （不处于左击状态）
  that.dm.currentDraw = null; // 当前绘图实例 初始化
}

/**
 * 鼠标移动的主要逻辑函数， 包括绘图,移动图形,拖拽图片,改变图形大小等
 * @private
 * @flow 根据当前绘制状态进行不同的 逻辑实现
 */
function _svgToMoveHandle(e) {
  var type = that.vm.type || 'click', // 当前绘制类型
    drawStatus = that.dm.drawStatus, // 当前绘制状态（是否处于左击状态）
    selectDomIsDraw = that.dm.selectDomIsDraw, // 当前选择的图形是否可以拖拽
    canDrag = /^r-\d+|^p-\d+|^opl-\d+/g.test(that.vm.selectId), // 当前图形是可以拖拽的
    isSameDom = (that.vm.selectId === that.dm.interimSelectId), // 根据临时图形 和 selectId 来判断是否是同一个图形
    isDragPoint = that.dm.isDragPoint, // 是否是拖动点
    selectPointId = that.dm.selectPointId; // 零时点
  if (drawStatus) { // 只有当前 处于 左击状态 才会有后续处理

    if (type === 'rect') { // 矩形
      _svgToDrawRect(e);
    } else if (type === 'polygon') { // 多边形
      _svgToMovePolygon(e)
    } else if (type === 'drag' && that.dm.isDrag) { // 拖拽 当前处于 拖拽状态
      _svgToMoveDrag(e)
    } else if (type === 'polyline') { // 多边形中的折线
      _svgToMovePolyLine(e) // 折线
    } else if (type === 'overPolyline') { // 非多边形中的折线
      _svgToMovePolygon(e)
    } else if (type === 'closeOverPolyline') { // 多边形中的折线
      _svgToMoveCloseOverPolyline(e)
    } else { // 此时应该为选择状态
      if (selectDomIsDraw && canDrag && isSameDom && !isDragPoint) { // 可拖拽，表示当前的图形是绘制出来的 出现了一个问题 那就是 本次应该拖拽的图形和上次不一样也可以拖拽
        _svgToMoveDraw(e); // 拖拽
        _hidePoint(e) // 隐藏拖拽点点
        if (typeof that.vm.graphicsMoveCallback === 'function') { // 修改图形后，可能存在回调函数
          that.vm.graphicsMoveCallback(e);
        }
      } else if (isDragPoint === true) { // 当前是拖动点
        var currentPoint = SVG.get(selectPointId), // 当前点的对象信息
          parentType = currentPoint.data('parent'); // 图形父元素的类型
        if (/^r-\d+/g.test(parentType)) { // 矩形点移动
          _rectMoveByPoint()
        } else if (/^p-\d+/g.test(parentType)) { // 多边形点移动
          var parent = currentPoint.data('parent'),
            name = parent + '-polyline',
            lines = SVG.select('.' + name),
            len = lines.members.length;
          if (!len) { // 当多边形下面没有折线的时候才可以移动
            _polyMoveByPoint()
          } else {
            SVG.get(selectPointId).removeClass('active'); // 如果不能移动要移除上面的class
          }
        } else if (/^pl-\d+/g.test(currentPoint.data('parent'))) { // 折线点移动
          _polyLineMoveByPoint();
        } else if (/^opl-\d+/g.test(parentType)) { // 非闭合折线点移动
          _polyMoveByPoint()
        } else if (/^copl-\d+/g.test(parentType)) { // 闭合折线点移动
          _closeOverPolylineMoveByPoint()
        }
        if (typeof that.vm.dragPointMoveCallback === 'function') { // 修改图形后，可能存在回调函数
          // that.vm.dragPointMoveCallback(e, SVG.get(selectPointId));
        }
      }
    }


    // 给外部一个点移动的回调  处理业务逻辑


  }
}

/**
 * 初始化点击状态 主要为了 拖拽上的问题
 * @private
 */
function _initClickStatus() {
  // alert(1);
  that.dm.selectDomIsDraw = false; // 取消拖拽状态
  that.dm.isDragPoint = false; // 初始化 点的状态
  that.dm.interimSelectId = ''; // 初始化临时 图形id
}

/**
 * 内部 隐藏非拖拽点
 * @private
 */
function _hidePoint() {
  var adjustSize = SVG.select('.adjust-size');
  adjustSize.each(function () {
    if (!this.hasClass('active')) { // 点击拖动的标记圆会有active类名
      this.hide();
    }
  });
}

/**
 * 内部 图形拖拽c
 * @private
 */
function _svgToMoveDraw() {
  var selectId = that.vm.selectId, // 当前选中
    currentDraw = SVG.get(selectId), // 当前选中的图形
    type = currentDraw.type,
    startPoint = currentDraw.data('selectPoint'), // 此图片原始的起始点
    currentPoint = that.dm.currentPoint, // 当前时时的点
    offsetX, offsetY;

  if (currentDraw) { // 存在实例
    offsetX = currentPoint.rx - startPoint.rx;
    offsetY = currentPoint.ry - startPoint.ry;
    currentDraw.dmove(offsetX, offsetY); // 移动到相对位置
    currentDraw.data('selectPoint', {
      rx: currentPoint.rx,
      ry: currentPoint.ry
    }); // 记录点
    _polylineMove(selectId, offsetX, offsetY); // 折线更改
    _textMove(selectId, offsetX, offsetY); // 文本移动
    _changeInfo(currentDraw, type); // 修改成功后的回调

  }
}

/**
 * 折线的移动
 * @private
 */
function _polylineMove(selectId, offsetX, offsetY) {
  var polyLines = SVG.select('.' + selectId + '-polyline'), // 获取当前图形下的所有折线
    members = polyLines.members;
  if (members.length > 0) {
    for (var i = 0; i < members.length; i++) {
      members[i].dmove(offsetX, offsetY);
      _changeInfo(members[i], 'polyline')
      // console.log('多边形内的折线的移动',members);
      _textMove(members[i].node.id, offsetX, offsetY)
    }
  }
}

/**
 * 文本的移动
 * @private
 */
function _textMove(selectId, offsetX, offsetY, type) {
  var text = SVG.get(selectId + '-text'); // 获取当前图形下的所有折线
  // console.log(selectId);
  if (type == 'rect') {
    text.move(offsetX, offsetY);
  } else {
    text.dmove(offsetX, offsetY);
  }
  _changeInfo(text, 'text')

}

/**
 * 内部 大图拖拽事件
 * @param e
 * @private
 */
function _svgToMoveDrag(e) {
  var dragPoint = that.dm.lastClickPoint,
    currentPoint = that.dm.currentPoint;
  // console.log(currentPoint)
  that.vm.imgData.x = that.vm.imgData.x + currentPoint.x - dragPoint.x;
  that.vm.imgData.y = that.vm.imgData.y + currentPoint.y - dragPoint.y;
  _render();

  _getPoint(e, 1); // 获取上次点击的坐标
}

/**
 * 矩形移动拖拽点
 * @private
 * @process ① 根据当前点计算移动的距离 重新绘图 ② 重新设置数据
 */
function _rectMoveByPoint() {
  var currentPointId = that.dm.selectPointId, // 当前点的id
    currentPoint = SVG.get(currentPointId), // 当前点
    currentSvg = SVG.get(currentPoint.data('parent')), // 当前点归属的图形
    type = currentSvg.type, // 图形类型
    lastPoint = currentPoint.data('bPoint'), // 上次点的位置
    cx = that.dm.currentPoint.rx, // 当前鼠标x位置
    cy = that.dm.currentPoint.ry, // 当前鼠标 y 位置
    px = cx - lastPoint.bx, // 偏移x的位置
    py = cy - lastPoint.by, // 偏移y 的位置
    circleX = currentPoint.cx(), // 圆心x的位置
    circleY = currentPoint.cy(), // 圆心y的位置
    diagonalPoints = currentPoint.data('diagonalPoints'), // 获取对角点
    nWidth = Math.abs(circleX - diagonalPoints[0]), // 新的矩形高度
    nHeight = Math.abs(circleY - diagonalPoints[1]); // 新的矩形宽度

  // 隐藏其他几个点
  _hidePoint();

  // console.log('矩形  当前选中的点' , currentPoint ,currentSvg.x(), currentSvg.y());
  SVG.get(currentPointId).dmove(px, py); // 移动当前选中的点
  currentPoint.data('bPoint', {
    bx: cx,
    by: cy
  }); // 赋值
  currentSvg.size(nWidth, nHeight).move(Math.min(cx, diagonalPoints[0]), Math.min(cy, diagonalPoints[1]));


  _textMove(that.vm.selectId, currentSvg.x(), currentSvg.y(), 'rect');

  _changeInfo(currentSvg, type)
}

/**
 * 拖拽 多边形的 拖拽点
 * @private
 * @process ① 根据当前点计算移动的距离 重新绘图 ② 重新设置数据 ③ 隐藏点
 */
function _polyMoveByPoint() {
  var currentPointId = that.dm.selectPointId, // 当前拖拽点的id
    currentPoint = SVG.get(currentPointId), // 当前点
    currentSvg = SVG.get(currentPoint.data('parent')), // 当前图形
    type = currentSvg.type, // 当前图形的类别
    lastPoint = currentPoint.data('bPoint'), // 上次点的位置
    cx = that.dm.currentPoint.rx, // 当前鼠标x位置
    cy = that.dm.currentPoint.ry, // 当前鼠标 y 位置
    px = cx - lastPoint.bx, // 偏移x的位置
    py = cy - lastPoint.by, // 偏移y 的位置
    circleX = currentPoint.cx(), // 圆心x的位置
    circleY = currentPoint.cy(), // 圆心y的位置
    points = currentSvg.array().value, // 所有点的值
    pointIndex, // 被点击的点的索引
    originalPoint = {
      cx: currentPoint.cx(),
      cy: currentPoint.cy()
    }, // 记录的被拖动的多边形的点
    freshPoint;
  // 找到当前点的是哪个拖拽点
  points.forEach(function (point, i) {
    if (point[0].toFixed(6) === originalPoint.cx.toFixed(6) && point[1].toFixed(6) === originalPoint.cy.toFixed(6)) {
      pointIndex = i;
      // 如果还出现获取点不准确 用生成点设置的point-index值来获取I
    }
  });

  // console.log(currentPoint, that.dm.currentPoint,lastPoint,px,py,111111111122222222233333333344444444445555555)
  //  alert(123)
  _hidePoint(); // 隐藏多余的点
  currentPoint.dmove(px, py); // 移动当前选中的点
  currentPoint.data('bPoint', {
    bx: that.dm.currentPoint.rx,
    by: that.dm.currentPoint.ry
  }); // 赋值

  freshPoint = [currentPoint.cx(), currentPoint.cy()]; // 获取圆心点坐标
  points.splice(pointIndex, 1, freshPoint);
  currentSvg.plot(points); // 重新绘制多边形

  if (pointIndex == 0) {
    _textMove(that.vm.selectId, px, py);
  }
  _changeInfo(currentSvg, type)
}

/**
 * 折线点的移动
 * @private
 */
function _polyLineMoveByPoint() {
  var selectPointId = that.dm.selectPointId,
    currentPoint = SVG.get(selectPointId), // 当前点
    currentSvg = SVG.get(currentPoint.data('parent')), // 当前图形
    type = currentSvg.type, // 当前图形的类别
    lastPoint = currentPoint.data('bPoint'), // 上次点的位置
    currentPointW = that.dm.currentPoint, // 当前鼠标位置
    cx = currentPointW.rx, // 当前鼠标x位置
    cy = currentPointW.ry, // 当前鼠标 y 位置
    px = cx - lastPoint.bx, // 偏移x的位置
    py = cy - lastPoint.by, // 偏移y 的位置
    circleX = currentPoint.cx(), // 圆心x的位置
    circleY = currentPoint.cy(), // 圆心y的位置
    points = currentSvg.array().value, // 所有点的值
    pointIndex, freshPoint, // 被点击的点的索引
    originalPoint = {
      cx: circleX,
      cy: circleY
    }; // 记录的被拖动的多边形的点

  points.forEach(function (point, i) {
    if (point[0] === originalPoint.cx && point[1] === originalPoint.cy) {
      pointIndex = i;
    }
  });

  if (pointIndex === 0 || pointIndex === points.length - 1) {
    return
  }

  _hidePoint();

  currentPoint.dmove(px, py); // 移动当前选中的点
  currentPoint.data('bPoint', {
    bx: cx,
    by: cy
  }); // 赋值

  freshPoint = [currentPoint.cx(), currentPoint.cy()]; // 获取圆心点坐标
  points.splice(pointIndex, 1, freshPoint);

  currentSvg.plot(points);
  //  console.log('移动折线的点');
  //  if(pointIndex == 1){
  //      _textMove(that.vm.selectId, px, py);
  //  }
  _changeInfo(currentSvg, type)
}

/**
 * 拖拽 单独封闭折线 拖拽点
 * @private
 * @process ① 根据当前点计算移动的距离 重新绘图 ② 重新设置数据 ③ 隐藏点
 */
function _closeOverPolylineMoveByPoint() {
  var currentPointId = that.dm.selectPointId, // 当前拖拽点的id
    currentPoint = SVG.get(currentPointId), // 当前点
    currentSvg = SVG.get(currentPoint.data('parent')), // 当前图形
    type = currentSvg.type, // 当前图形的类别
    lastPoint = currentPoint.data('bPoint'), // 上次点的位置
    cx = that.dm.currentPoint.rx, // 当前鼠标x位置
    cy = that.dm.currentPoint.ry, // 当前鼠标 y 位置
    px = cx - lastPoint.bx, // 偏移x的位置
    py = cy - lastPoint.by, // 偏移y 的位置
    circleX = currentPoint.cx(), // 圆心x的位置
    circleY = currentPoint.cy(), // 圆心y的位置
    points = currentSvg.array().value, // 所有点的值
    pointIndex, // 被点击的点的索引
    originalPoint = {
      cx: currentPoint.cx(),
      cy: currentPoint.cy()
    }, // 记录的被拖动的多边形的点
    freshPoint;

  // 找到当前点的是哪个拖拽点
  points.forEach(function (point, i) {
    if (point[0] === originalPoint.cx && point[1] === originalPoint.cy) {
      pointIndex = i;
    }
  });

  // console.log(pointIndex,points.length-1);
  //禁止最后一个点和第一个点拖拽
  if (pointIndex === 0 || pointIndex === points.length - 1) {
    return
  }


  _hidePoint(); // 隐藏多余的点
  currentPoint.dmove(px, py); // 移动当前选中的点
  currentPoint.data('bPoint', {
    bx: that.dm.currentPoint.rx,
    by: that.dm.currentPoint.ry
  }); // 赋值
  freshPoint = [currentPoint.cx(), currentPoint.cy()]; // 获取圆心点坐标
  points.splice(pointIndex, 1, freshPoint);
  currentSvg.plot(points); // 重新绘制多边形

  if (pointIndex == 0) {
    _textMove(that.vm.selectId, px, py);
  }
  _changeInfo(currentSvg, type)
}

/**
 * 绘制结束 （需要校验图形是否符合规则，然后判断是否进行下一步操作）
 * 矩形,多边形等都需要进行校验 看图形是否符合规则
 * 校验完毕就是数据交互，等操作
 * @private
 */
function _checkCurrentDraw() {
  var currentDraw = that.dm.currentDraw, // 当前绘制的图形实例
    type = that.vm.type, // 当前绘制类别
    height, width = 0,
    point, pointNum, id;

  if (currentDraw) { // 检验是否符合标准
    height = currentDraw.height();
    width = currentDraw.width();
    id = currentDraw.id();

    if (type !== 'polyline' && type !== 'closeOverPolyline') { // 只有不是 折线时 才会校验
      if (height < 10 || width < 10) {
        currentDraw.remove();
        _drawFail();
        return false
      }
    }
  } else { // 不存在绘图实例，直接返回
    if (type !== 'polyline' && type !== 'closeOverPolyline') { // 考虑到 右键直接绘制
      // _drawFail()
      return false;
    }
  }

  if (type === 'polygon') { // 多边形的情况
    if (that.dm.drawStatus) { // 表示还处在绘图状态，才会触发（避免多次触发该事件）
      point = that.dm.currentDraw.array().value.slice(0);
      pointNum = point.length;
      var direction = getPolygonDirection(point); // 相隔两点叉乘求面积 判断多边形绘制方向
      if (pointNum < 4) {
        currentDraw.remove();
        _drawFail()
        return false
      } else {
        point.pop();
        if (direction < 0) { // 逆时针 精细化标注业务线需求 逆时针方向绘制不闭合折线 
          currentDraw.remove();
          _drawFail('counterclockwise')
          return false
        } else { // 顺时针
          currentDraw.plot(point);
        }
      }
    }
  } else if (type === 'polyline' || type === 'closeOverPolyline') { // 折线的情况
    _drawPolyLineEnd(); // 对折线进行操作
    // currentDraw = that.dm.currentDraw; // 因为重新绘制图形，重新获取实例
    // id = currentDraw.id(); // 因为重新绘制图形，重新获取id
  }

  // 校验成功后
  if (that.dm.currentDraw) {
    currentDraw = that.dm.currentDraw;
    id = currentDraw.id(); // 之前业务中 不存在实例 必然 return 现在多了一个 折线 所以需要做判断
    _setDrawParent(id, type);
    _drawSuccess(currentDraw); // 成功绘制
  } else {

  }
}

/**
 * 成功绘制完成
 * @private
 */
function _drawSuccess(currentDraw) {
  // 成功后的数据交互（由于业务逻辑过于复杂，放到业务中做）
  if (typeof that.vm.successCallBack === 'function') {
    that.vm.selectId = currentDraw.id();
    that.vm.successCallBack(currentDraw)
  }
}
/**
 * 绘制失败
 * @private
 */
function _drawFail(failType) {
  // 成功后的数据交互（由于业务逻辑过于复杂，放到业务中做）
  if (typeof that.vm.drawFailCallBack === 'function') {
    that.vm.drawFailCallBack(failType)
  }
}

/**
 * 图形修改成功后
 * @param currentDraw
 * @param type
 * @private
 */
function _changeInfo(currentDraw, type) {
  // var id = currentDraw;
  if (typeof that.vm.changeCallBack === 'function') { // 修改图形后，可能存在回调函数
    that.vm.changeCallBack(currentDraw);
  }
}

/**
 * 给绘制的图形增加一个组别 （暂时不知道是否需要）
 */
function _setDrawParent(id, type) {
  if (/^pl-\d+/g.test(id)) {
    return
  } // 折线不给自己添加组
  var svgNode = SVG.get(id),
    groupId = id + '-group',
    parentGroup = that.dm.defaultGroup.group().attr({
      id: groupId,
      class: 'area-box-group'
    });
  parentGroup.add(svgNode);
  // 给svg元素添加单击事件
  svgNode.on('click', function (e) {
    if (typeof that.vm.svgNodeClickCallBack === 'function') { // 修改图形后，可能存在回调函数
      that.vm.svgNodeClickCallBack(e, svgNode);
    }
  })
  // 给svg元素添加双击事件
  svgNode.on('dblclick', function (e) {
    if (typeof that.vm.svgNodeDblclickCallBack === 'function') { // 修改图形后，可能存在回调函数
      that.vm.svgNodeDblclickCallBack(e, svgNode);
    }
  })
  _setTextByDraw(svgNode, parentGroup, id);
}

/**
 * 绘制文本
 * @param svgNode
 * @param parentGroup
 * @param id
 * @private
 */
function _setTextByDraw(svgNode, parentGroup, id, isShow) {
  var type = svgNode.type,
    x, y, point, textSize = that.vm.textSize / (that.vm.zoom < 1 ? 1 : that.vm.zoom);
  if (type === 'rect') {
    x = svgNode.x();
    y = svgNode.y();
  } else if (type === 'polygon' || type === 'polyline') {
    point = svgNode.array().value[0];
    x = point[0];
    y = point[1];
  }
  var textDom = parentGroup.text(id + '-text').move(x, y).font({
    fill: '#f06',
    family: 'Inconsolata',
    size: textSize
  }).attr({
    id: id + '-text',
    display: isShow ? 'block' : 'none'
  })
}

/**
 * 结尾线绘制
 * @private
 */
function _drawPolyLineEnd() {
  var currentDraw = that.dm.currentDraw,
    currentEndNearPoint = that.dm.currentEndNearPoint,
    currentStartNearPoint = that.dm.currentStartNearPoint,
    point;
  if (currentDraw) {

    point = currentDraw.array().value.slice(0);
    // 删除水平线和交叉点
    _drawPoint('delAll');
    _deleteLine();
    // 把最近的两个交叉点添加到折线里
    if (currentEndNearPoint.x !== '' && currentEndNearPoint.y !== '') { //
      point.push([currentEndNearPoint.x, currentEndNearPoint.y]);
    }

    if (currentStartNearPoint.x !== '' && currentStartNearPoint.y !== '') {
      point.unshift([currentStartNearPoint.x, currentStartNearPoint.y]);
    }
    currentDraw.plot(point);


  } else { // e

    // console.log('直接结束绘制',that.dm.isOnPolyLine);
    // if(that.vm.type !== 'closeOverPolyline' && that.dm.isOnPolyLine){ // 在多边形中
    //   _svgToDrawPolyLine('stopDraw');
    // }else{
    //   _drawPoint('delAll');
    //   _deleteLine();
    // }

    if (that.vm.type !== 'closeOverPolyline' && that.dm.isOnPolyLine) { // 在多边形中
      _svgToDrawPolyLine('stopDraw');
    } else if (that.vm.type == 'closeOverPolyline') {
      _svgToDrawCloseOverPolyLine('stopDraw');

    } else {
      _drawPoint('delAll');
      _deleteLine();
    }
  }

  //当折线绘制结束 生成完整的折线时 绘制文本
  // console.log('currentDraw currentDraw',currentDraw , SVG.get(that.vm.selectId+'-group'));
  if (that.vm.type === 'closeOverPolyline') return;
  if (currentDraw) {
    _setTextByDraw(that.dm.currentDraw, SVG.get(that.vm.selectId + '-group'), that.vm.currentPolyLineId); // 增加文本
  } else if (!currentDraw && that.dm.isOnPolyLine) {
    _setTextByDraw(that.dm.currentDraw, SVG.get('defaultGroup'), that.vm.currentPolyLineId); // 增加文本
  }

}

/**
 * 折线绘制，多边形形中的折线
 * @param status 状态参数
 * @private
 */
function _svgToDrawPolyLine(status) {
  var currentDraw = that.dm.currentDraw, // 当前绘制的实例
    lastPoint = that.dm.lastClickPoint, // 上次点下的点
    currentPoint = that.dm.currentPoint, // 时时的点
    rx = currentPoint.rx, // 相对 x 的位置
    ry = currentPoint.ry, // 相对 y 的位置
    points, id, selectId = that.vm.selectId; // 需要绘制的点
  // 校验是否在多边形中
  if (!that.dm.isOnPolyLine) {
    ////////// 强制性指向修复
    // that.vm.type = 'click';
    // _svgClick(window.event, 1);
    ///////////
    return;
  }

  if (!currentDraw) { // 没有创建一个新的实例
    id = that.vm.currentPolyLineId = _createOnlyNumber();
    points = [
      [lastPoint.rx, lastPoint.ry],
      [lastPoint.rx, lastPoint.ry]
    ];

    //
    if (status === 'stopDraw') {
      points = [
        [that.dm.currentStartNearPoint.x, that.dm.currentStartNearPoint.y],
        [that.dm.currentEndNearPoint.x, that.dm.currentEndNearPoint.y]
      ];
    }

    // 折线绘制
    that.dm.currentDraw = that.dm.defaultGroup.polyline(points).attr({
      id: id,
      class: 'area-box ' + selectId + '-polyline',
      stroke: plColor,
      'stroke-width': that.vm.strokeWidth,
    }).fill({
      color: plColor,
      opacity: '0'
    }).data({
      parent: selectId
    });
    // 把当前折线放到所属的多边形组里

    SVG.get(that.vm.selectId + '-group').add(that.dm.currentDraw); // 增加当前组
    // _setTextByDraw(that.dm.currentDraw,SVG.get(that.vm.selectId+'-group'),id); // 增加文本 （放到折线绘制结束时绘制文本，避免文本在第二个点）

  } else {
    points = currentDraw.array().value.slice(0);
    points.push([rx, ry]);
    currentDraw.plot(points);
  }


  if (status !== 'stopDraw') {
    _drawHorizon(that.dm.currentDraw, points[0], points[points.length - 1]);
  } else {
    _drawPoint('delAll');
    _deleteLine(); // 删除水平线
  }
}


/**
 * 删除水平线
 * @private
 */
function _deleteLine() {
  var allLine;
  try {
    allLine = SVG.select('line');
    allLine.members.map(function (k, v) {
      if (k.id().indexOf('horizonLine-') !== -1) {
        k.remove();
      }
    });
  } catch (e) {
    warnInfo('不存在水平线');
  }
}

/**
 * 根据点绘制水平线
 * drawObject 当前多边形实例
 * startPoint 折线开始的点
 * endPoint 折现结束的点
 * @private
 */
function _drawHorizon(drawObject, startPoint, endPoint) {

  // 校验是否是对象
  if (typeof drawObject !== 'object') {
    return;
  }

  // 校验是否在多边形中
  // if (!that.dm.isOnPolyLine) {
  //   return;
  // }

  var polyLineId = that.vm.currentPolyLineId, // 当前折线的id ( zx注-->只有点击后才能拿到当前的分行线id 不点击是上一个绘制折线的id)
    allPoint = _sumAllPoint(drawObject, startPoint, endPoint), // 所有的焦点
    selectId = that.vm.selectId == 'defaultGroup' || !that.vm.selectId ? 'image-border' : that.vm.selectId, // 当前选择的id
    currentDraw = that.dm.currentDraw, // 当前绘制的实例对象
    startNearPoint, endNearPoint,
    polyLineStartName, polyLineEndName,
    polyLineStartObject, polyLineEndObject, // 折线对象
    startH, // 开始点延伸出的水平线
    endH; // 结束点延伸出的水平线
  // 求最近的点
  startNearPoint = sumNearPoint(startPoint, allPoint.startHorizonPoint);
  endNearPoint = sumNearPoint(endPoint, allPoint.endHorizonPoint);
  polyLineStartName = 'horizonLine-start-' + selectId; // 'horizonLine-start-'+ polyLineId +'-'+ selectId;
  polyLineEndName = 'horizonLine-end-' + selectId; // 'horizonLine-end-'+ polyLineId +'-'+ selectId;
  polyLineStartObject = SVG.get(polyLineStartName);
  polyLineEndObject = SVG.get(polyLineEndName);

  // that.dm.currentEndNearPoint = endNearPoint; // 赋值最近的点

  if (startNearPoint.x === '' || endNearPoint.x === '') {
    return
  } // 如果 最近 或者 最远的点都不存在

  that.dm.currentEndNearPoint = endNearPoint; // 赋值最近的点 (修改位置避免bug)

  //绘制交点
  _drawPoint(endNearPoint);

  //移除当前选中多边形的结束的水平线 以免绘制重复
  if (polyLineStartObject) {
    polyLineEndObject.remove();
    if (!currentDraw) {
      polyLineStartObject.remove();
    }
  }

  if (!currentDraw || !polyLineStartObject) {
    that.dm.currentStartNearPoint = startNearPoint;
    _drawPoint(startNearPoint, 'start-' + polyLineId); // 'start-'+ polyLineId 绘制当前点与最近结束点连线 
    //绘制开始点延伸出的水平线
    startH = that.dm.defaultGroup.line(startPoint[0], startPoint[1], startNearPoint.x, startNearPoint.y).attr({
      id: 'horizonLine-start-' + selectId,
      class: 'horizonLine',
      parentId: selectId
    }).stroke({
      color: plColor,
      width: that.vm.strokeWidth,
      linecap: 'round'
    }).data('parent', selectId);
    // 'horizonLine-start-' + polyLineId +'-'+ selectId
    if (that.vm.type !== 'closeOverPolyline') {
      SVG.get(selectId + '-group').add(startH);
    } else {
      SVG.get('defaultGroup').add(startH);
    }

  }


  //绘制结束点延伸出的水平线
  endH = that.dm.defaultGroup.line(endPoint[0], endPoint[1], endNearPoint.x, endNearPoint.y).attr({
    id: 'horizonLine-end-' + selectId,
    class: that.vm.svgHightLightClass + ' horizonLine',
    parentId: selectId
  }).stroke({
    color: plColor,
    width: that.vm.strokeWidth,
    linecap: 'round'
  }).data('parent', selectId);
  // 'horizonLine-end-' + polyLineId + '-'+ selectId
  if (that.vm.type !== 'closeOverPolyline') {
    SVG.get(selectId + '-group').add(endH);
  } else {
    SVG.get('defaultGroup').add(endH);
  }
}


/**
 * 求当前折线的起止点延伸出的水平线 和 图形的所有交点
 * @param draw 折线实例对象
 * @param startPoint 开始的点
 * @param endPoint 结束的点
 * @private
 */
function _sumAllPoint(draw, startPoint, endPoint) {
  var width = that.vm.imgData.width, // 图片宽度
    selectId = that.vm.selectId == 'defaultGroup' || !that.vm.selectId ? 'image-border' : that.vm.selectId, // 当前选择的id
    polygon = SVG.get(selectId), // 选择的图形对象
    points, // 多边形的点
    a = {},
    b = {},
    c = {},
    d = {},
    e = {},
    f = {},
    endHorizonPoint = [],
    startHorizonPoint = [],
    currentPoints;

  //终点线段的两个点
  c.x = endPoint[0];
  c.y = endPoint[1];
  d.x = endPoint[0] + width;
  d.y = endPoint[1];

  points = polygon.array().value; // 多边形的点
  // 当前选中图形的点
  currentPoints = pointjrx(points); // [[x1,y1],[x2,y2],[x3,y3]....]
  //求相交点
  for (var i = 0; i < currentPoints.length; i++) {
    if (i < currentPoints.length - 1) {
      a.x = currentPoints[i][0];
      a.y = currentPoints[i][1];
      b.x = currentPoints[i + 1][0];
      b.y = currentPoints[i + 1][1];
    } else {
      a.x = currentPoints[i][0];
      a.y = currentPoints[i][1];
      b.x = currentPoints[0][0];
      b.y = currentPoints[0][1];
    }

    //如果存在交点则存到数组里
    if (segmentsIntr(a, b, c, d, 'end')) { // 两条线的交点
      endHorizonPoint.push(segmentsIntr(a, b, c, d, 'end'));
    }
  }

  //起点线段的点
  e.x = startPoint[0];
  e.y = startPoint[1];
  f.x = startPoint[0] - width;
  f.y = startPoint[1];

  for (var i = 0; i < currentPoints.length; i++) {
    // console.log('求起点相交点',currentPoints,currentPoints.length);
    if (i < currentPoints.length - 1) {
      a.x = currentPoints[i][0];
      a.y = currentPoints[i][1];
      b.x = currentPoints[i + 1][0];
      b.y = currentPoints[i + 1][1];
    } else {
      a.x = currentPoints[i][0];
      a.y = currentPoints[i][1];
      b.x = currentPoints[0][0];
      b.y = currentPoints[0][1];
    }
    if (segmentsIntr(a, b, e, f, 'start')) {
      startHorizonPoint.push(segmentsIntr(a, b, e, f, 'start'));
    }
  }
  return {
    startHorizonPoint,
    endHorizonPoint
  }
}

/**
 * 绘制交点函数  point 标准点坐标 (null 时删除所有点) horizonPoint 水平线和图形的所有交点 【type 点类型】
 * @param point
 * @param type
 * @private
 */
function _drawPoint(point, type) {
  // 删除已存在的同一类型的点
  var allLine = Array.prototype.slice.call(that.dm.defaultGroup.node.childNodes),
    overPoint,
    dragPointSize = that.vm.dragPointSize / (that.vm.zoom < 1 ? 1 : that.vm.zoom),
    halfDragPointSize = dragPointSize / 2;

  allLine.forEach(function (k, v) { // 删除所有的直线
    if (k.className.animVal.indexOf(type) !== -1) {
      k.remove();
    }
  });

  if (point === 'delAll') { // 删除所有的点
    allLine.forEach(function (k, v) {
      if (k.className.animVal.indexOf('nearPoint') !== -1) {
        k.remove();
      }
    });
    return;
  }

  // 绘制点
  overPoint = that.dm.defaultGroup.circle(dragPointSize).attr({
    id: 'overPoint',
    class: type + ' nearPoint',
  }).fill('yellow').move(point.x - halfDragPointSize, point.y - halfDragPointSize);

  // console.log(SVG.select('.nearPoint'));
  // if (/^p-\d+/g.test(that.vm.selectId)) {
  //   SVG.get('overPoint'+ type).remove();
  //   SVG.get(that.vm.selectId + '-group').add(overPoint);
  // }
  overPoint.back(); // 置底
  SVG.get('svgImage').back()
}

/**
 *  矩形绘制
 * @private
 */
function _svgToDrawRect(e) {
  var currentDraw = that.dm.currentDraw, // 当前绘制的实例
    lastPoint = that.dm.lastClickPoint, // 上次点下的点
    currentPoint = that.dm.currentPoint, // 当前时时的点
    id = '', // 当前矩形的id
    width = 0, // 矩形的宽度
    height = 0, // 矩形的高度
    rx = 0, // 矩形起始点
    ry = 0; // 矩形起始点

  if (!currentDraw) { // 没有创建一个新的实例
    id = _createOnlyNumber(); // 获取当前的id
    that.dm.currentDraw = createRect(lastPoint, id, rColor, 0)
  } else {
    width = Math.abs(currentPoint.rx - lastPoint.rx); // 矩形的宽度
    height = Math.abs(currentPoint.ry - lastPoint.ry); // 矩形的高度
    rx = Math.min(lastPoint.rx, currentPoint.rx); //  矩形起始点 取最小的点
    ry = Math.min(lastPoint.ry, currentPoint.ry); //  矩形起始点 取最小的点

    currentDraw.stroke({
      color: rColor,
      width: that.vm.strokeWidth,
      linecap: 'round',
      linejoin: 'miter'
    });
    currentDraw.size(width, height).move(rx, ry) // .data('startPoint',{rx:rx,ry:ry})
  }
}

/**
 *  多边形绘制 (是否存在矩形实例) (多边形点击绘制)
 * @private
 */
function _svgToDrawPolygon() {
  var currentDraw = that.dm.currentDraw, // 当前绘制的实例
    lastPoint = that.dm.lastClickPoint, // 上次点下的点
    rx = that.dm.currentPoint.rx, // 相对 x 的位置
    ry = that.dm.currentPoint.ry, // 相对 y 的位置
    points, // 需要绘制的点
    id; // 名称 id
  if (!currentDraw) { // 没有创建一个新的实例
    id = _createOnlyNumber();
    points = [
      [lastPoint.rx, lastPoint.ry],
      [lastPoint.rx, lastPoint.ry]
    ];
    that.dm.currentDraw = that.dm.defaultGroup.polygon(points).attr({
      id: id,
      class: 'area-box',
      stroke: pColor,
      'stroke-width': that.vm.strokeWidth
    }).fill({
      color: pColor,
      opacity: 0
    });
  } else {
    points = currentDraw.array().value.slice(0);
    points.push([rx, ry]);
    currentDraw.plot(points);
  }
}

/**
 * 绘制多边形时，移动鼠标
 * @private
 */
function _svgToMovePolygon() {
  var currentDraw = that.dm.currentDraw, // 当前绘制的实例
    rx = that.dm.currentPoint.rx, // 相对 x 的位置
    ry = that.dm.currentPoint.ry, // 相对 y 的位置
    polygonPoint = currentDraw.array().value.slice(0);

  polygonPoint.splice(-1, 1, [rx, ry]);
  currentDraw.plot(polygonPoint);
}

/**
 * 绘制多边形时，移动鼠标
 * @private
 */
function _svgToMoveCloseOverPolyline() {
  var currentDraw = that.dm.currentDraw, // 当前绘制的实例
    rx = that.dm.currentPoint.rx, // 相对 x 的位置
    ry = that.dm.currentPoint.ry, // 相对 y 的位置
    polygonPoint = currentDraw.array().value.slice(0);
  polygonPoint.splice(-1, 1, [rx, ry]);
  currentDraw.plot(polygonPoint);
}

/**
 *  单独折线绘制 (是否存在矩形实例) ( 不闭合折线 )
 * @private
 */
function _svgToDrawOverPolyLine() {
  var currentDraw = that.dm.currentDraw, // 当前绘制的实例
    lastPoint = that.dm.lastClickPoint, // 上次点下的点
    rx = that.dm.currentPoint.rx, // 相对 x 的位置
    ry = that.dm.currentPoint.ry, // 相对 y 的位置
    points, // 需要绘制的点
    id; // 名称 id

  if (!currentDraw) { // 没有创建一个新的实例
    id = _createOnlyNumber();
    points = [
      [lastPoint.rx, lastPoint.ry],
      [lastPoint.rx, lastPoint.ry]
    ];
    that.dm.currentDraw = that.dm.defaultGroup.polyline(points).attr({
      id: id,
      class: 'area-box',
      stroke: '#fe00ff',
      'stroke-width': that.vm.strokeWidth
    }).fill({
      color: '#3656bf',
      opacity: '0'
    });
  } else {
    points = currentDraw.array().value.slice(0);
    points.push([rx, ry]);
    currentDraw.plot(points);
  }
}

/**
 *  单独闭合折线绘制 (是否存在实例)
 * @private
 */
function _svgToDrawCloseOverPolyLine(status) {
  var currentDraw = that.dm.currentDraw, // 当前绘制的实例
    lastPoint = that.dm.lastClickPoint, // 上次点下的点
    rx = that.dm.currentPoint.rx, // 相对 x 的位置
    ry = that.dm.currentPoint.ry, // 相对 y 的位置
    points, // 需要绘制的点
    id, selectId = that.vm.selectId; // 名称 id
  // if (!currentDraw) { // 没有创建一个新的实例
  //     id = _createOnlyNumber();
  //     points = [[lastPoint.rx, lastPoint.ry], [lastPoint.rx, lastPoint.ry]];
  //     that.dm.currentDraw = that.dm.defaultGroup.polyline(points).attr({
  //         id: id,
  //         class: 'area-box',
  //         stroke: '#fe00ff',
  //         'stroke-width': that.vm.strokeWidth
  //     }).fill({color: '#3656bf', opacity: '0'});
  // } else {
  //     points = currentDraw.array().value.slice(0);
  //     points.push([rx, ry]);
  //     currentDraw.plot(points);
  // }


  if (!currentDraw) { // 没有创建一个新的实例

    id = that.vm.currentPolyLineId = _createOnlyNumber();
    points = [
      [lastPoint.rx, lastPoint.ry],
      [lastPoint.rx, lastPoint.ry]
    ];
    if (status === 'stopDraw') {
      points = [
        [that.dm.currentStartNearPoint.x, that.dm.currentStartNearPoint.y],
        [that.dm.currentEndNearPoint.x, that.dm.currentEndNearPoint.y]
      ];
    }

    // 折线绘制
    that.dm.currentDraw = that.dm.defaultGroup.polyline(points).attr({
      id: id,
      class: 'area-box ' + id + '-polyline copl-polyline',
      stroke: 'red',
      'stroke-width': that.vm.strokeWidth,
    }).fill({
      color: '#3656bf',
      opacity: '0'
    }).data({
      parent: id
    });

    // 把当前折线放到所属的多边形组里
    SVG.get('defaultGroup').add(that.dm.currentDraw); // 增加当前组
    // _setTextByDraw(that.dm.currentDraw,SVG.get('defaultGroup'),id); // 增加文本  （放到折线绘制结束时绘制文本，避免文本在第二个点）

  } else {

    points = currentDraw.array().value.slice(0);
    points.push([rx, ry]);
    currentDraw.plot(points);
  }


  // console.log('绘制直线1111111');

  if (status !== 'stopDraw') {
    _drawHorizon(that.dm.currentDraw, points[0], points[points.length - 1]);
  } else {
    _drawPoint('delAll');
    _deleteLine(); // 删除水平线
  }

}




/**
 * 折线绘制时
 * @private
 */
function _svgToMovePolyLine(e) {
  // 校验是否在多边形中
  if (!that.dm.isOnPolyLine) {
    return;
  }

  var currentDraw = that.dm.currentDraw; // 当前绘制的实例
  if (currentDraw) { // 确定是否存在实例
    var polygonPoint = currentDraw.array().value.slice(0),
      currentPoint = that.dm.currentPoint,
      rx = currentPoint.rx,
      ry = currentPoint.ry;
    polygonPoint.splice(-1, 1, [rx, ry]);
    currentDraw.plot(polygonPoint);
  } else {

  }
}

/**
 * 生成唯一的id
 * @returns {string}
 * @private
 */
function _createOnlyNumber() {
  var type = that.vm.type,
    id = that.vm.currentId,
    name = 'init';
  if (type === 'rect') {
    name = 'r-' + id
  } else if (type === 'polygon') {
    name = 'p-' + id
  } else if (type === 'polyline') { // 折线等图形的实现
    name = 'pl-' + id
  } else if (type === 'overPolyline') { // 折线等图形的实现
    name = 'opl-' + id
  } else if (type === 'closeOverPolyline') { // 折线等图形的实现
    name = 'copl-' + id
  }

  that.vm.currentId++;
  return name
}

/**
 * 内部 设置十字光标 (矩形内部，和整体)
 * @param e
 * @private
 */
function _setCursor(e) {
  var graphY = that.dm.currentPoint.ry,
    graphX = that.dm.currentPoint.rx,
    type = that.vm.type,
    selectId = that.vm.selectId,
    point, currentSelectObject;

  if (type === 'polyline' || type === 'closeOverPolyline') {
    currentSelectObject = SVG.get(selectId);
    point = [graphX, graphY + 2]; // point
    _drawHorizon(currentSelectObject, point, point)
  } else {
    that.dm.lineX.front().plot(0, graphY + 1, that.dm.drawImg.width(), graphY + 1);
    that.dm.lineY.front().plot(graphX + 1, 0, graphX + 1, that.dm.drawImg.height());
  }
}

/**
 * 内部初始化光标
 * @private
 */
function _initCursor() {
  that.dm.lineX.front().plot(0, 0, 0, 0);
  that.dm.lineY.front().plot(0, 0, 0, 0);
}

/**
 * 获取点的坐标  优化实现方式  合并在一起
 * @param e
 * @param type 0 获取时时点的坐标 1 获取 mousedown 时点的坐标  2 获取 mouseup 时点的坐标
 * @private
 */
function _getPoint(e, type) {
  var zoom = that.vm.zoom;
  var name = type === 0 ? 'currentPoint' : (type === 1 ? 'lastClickPoint' : 'comparePoint');
  var x = 0,
    y = 0;
  if (agentFrom === 'Firefox') {
    x = e.layerX;
    y = e.layerY;
    that.dm[name].x = e.layerX; // 相对可视区域
    that.dm[name].y = e.layerY; // 相对可视区域
  } else {
    x = e.offsetX;
    y = e.offsetY;
    that.dm[name].x = e.offsetX; // 相对可视区域
    that.dm[name].y = e.offsetY; // 相对可视区域
  }

  if (that.vm.rotateDeg === 1) { // 旋转0°
    that.dm[name].rx = (x - that.vm.imgData.x) / zoom; // 理论上相对 defaultgroup的位置 (也就是说 当前鼠标位置 减去 当前图片所处的位置，处于缩放比例就是当前相对位置)
    that.dm[name].ry = (y - that.vm.imgData.y) / zoom // 理论上相对 defaultgroup的位置  
  } else if (that.vm.rotateDeg === 2) { // 旋转90°
    that.dm[name].rx = (y - that.vm.imgData.y) / zoom; // 理论上相对 defaultgroup的位置 (也就是说 当前鼠标位置 减去 当前图片所处的位置，处于缩放比例就是当前相对位置)
    that.dm[name].ry = -(x - that.vm.imgData.x) / zoom // 理论上相对 defaultgroup的位置
  } else if (that.vm.rotateDeg === 3) {
    that.dm[name].rx = -(x - that.vm.imgData.x) / zoom; // 理论上相对 defaultgroup的位置 (也就是说 当前鼠标位置 减去 当前图片所处的位置，处于缩放比例就是当前相对位置)
    that.dm[name].ry = $('#defaultGroup').height() - (y - that.vm.imgData.y) / zoom // 理论上相对 defaultgroup的位置
  } else if (that.vm.rotateDeg === 4) {
    that.dm[name].rx = -(y - that.vm.imgData.y) / zoom; // 理论上相对 defaultgroup的位置 (也就是说 当前鼠标位置 减去 当前图片所处的位置，处于缩放比例就是当前相对位置)
    that.dm[name].ry = (x - that.vm.imgData.x) / zoom; // 理论上相对 defaultgroup的位置
  }

}

/**
 * 缩放比例设置
 * @param el  挂载的 id
 * @private
 *  degType 旋转
 */
function _setZoom(el, degType) {
  // 基本属性
  var dom = document.getElementById(el), // svg dom element
    imgWidth = 0, // 当前图片宽度
    imgHeight = 0, // 当前图片高度
    drawWidth = dom.offsetWidth, // svg 本身的宽度
    drawHeight = dom.offsetHeight, // svg 本身的高度
    rx, ry, x, y, zoom = 1; // 相对x 相对y x y 缩放比


  // 过滤旋转
  if (degType !== undefined && (degType === 1 || degType === 3)) {
    imgWidth = that.vm.imgData.width; // 当前图片宽度
    imgHeight = that.vm.imgData.height; // 当前图片高度
  } else if (degType !== undefined && (degType === 2 || degType === 4)) {
    imgWidth = that.vm.imgData.height; // 当前图片宽度
    imgHeight = that.vm.imgData.width; // 当前图片高度
  }
  // 取最小的那个作为缩放比例
  if (imgWidth > drawWidth || imgHeight > drawHeight) {
    rx = drawWidth / imgWidth;
    ry = drawHeight / imgHeight;
    zoom = rx < ry ? rx : ry // 缩放比例
  }

  // 求图片的相对位置
  if (degType !== undefined && degType === 1) {
    x = Math.abs(drawWidth - imgWidth * zoom) / 2; // 图片相对于 svg x 值
    y = Math.abs(drawHeight - imgHeight * zoom) / 2; // 图片性对于 svg y 值  
  } else if (degType !== undefined && degType === 2) {
    x = Math.abs(drawWidth - imgWidth * zoom) / 2 + imgWidth * zoom; // 图片相对于 svg x 值
    y = Math.abs(drawHeight - imgHeight * zoom) / 2; // 图片性对于 svg y 值  
  } else if (degType !== undefined && degType === 3) {
    x = Math.abs(drawWidth - imgWidth * zoom) / 2 + imgWidth * zoom; // 图片相对于 svg x 值
    y = Math.abs(drawHeight - imgHeight * zoom) / 2 + imgHeight * zoom; // 图片性对于 svg y 值
  } else if (degType !== undefined && degType === 4) {
    x = Math.abs(drawWidth - imgWidth * zoom) / 2; // 图片相对于 svg x 值
    y = Math.abs(drawHeight - imgHeight * zoom) / 2 + imgHeight * zoom; // 图片性对于 svg y 值
  }
  _setData(zoom, x, y); // 属性设置
  _render(degType); // 渲染
}

/**
 * 内部设置属性 ( 不传入 x , y 默认 原本值)
 * @param zoom 缩放比例
 * @param x x轴坐标
 * @param y y轴坐标
 */
function _setData(zoom, x, y) {
  that.vm.zoom = zoom; // 设置当前 缩放比
  that.vm.imgData.x = (x !== undefined) ? x : that.vm.imgData.x; // 设置image 处于 相对于 svg 的 x轴位置
  that.vm.imgData.y = (y !== undefined) ? y : that.vm.imgData.y; //  设置 image 处于 相对于 svg 的 y轴位置
}

/**
 * 图形渲染,根据缩放比例，x，y
 */
function _render(degType) {
  var zoom = that.vm.zoom; // 缩放比
  var x = that.vm.imgData.x; // defaultGroup 相对 x 轴位置
  var y = that.vm.imgData.y; // defaultGroup 相对 y 轴位置
  var degType = degType === undefined ? that.vm.rotateDeg : degType;
  // var x = 20; // defaultGroup 相对 x 轴位置
  // var y = 0; // defaultGroup 相对 y 轴位置
  // var sin = 0,
  //     cos = 0;
  if (degType !== undefined) {
    var sin = Math.sin(Math.PI / 180 * (degType - 1) * 90),
      cos = Math.cos(Math.PI / 180 * (degType - 1) * 90);
  }

  if (degType === 1 || degType === 3) {
    var transform = "matrix(" + zoom * cos + "," + sin + "," + (-sin) + "," + cos * zoom + "," + x + "," + y + ")"; // 设置
  } else if (degType === 2 || degType === 4) {
    var transform = "matrix(" + cos + "," + zoom * sin + "," + (-sin * zoom) + "," + cos + "," + x + "," + y + ")"; // 设置
  }
  var defaultGroup = SVG.get('defaultGroup');
  defaultGroup.attr({
    'transform': transform
  });
}

/**
 *  旋转角度
 *  degType 0 0, 1 90, 2 180, 3 270
 */
OcrPublicClass.prototype.setImageAngle = function (degType) {
  if (degType !== undefined) {
    _setZoom(that.vm.el, degType); // 设置缩放比
    changeStrokeByZoom(that.dm.defaultGroup);
  }
}

/**
 *
 * @param width 宽度
 * @param color 颜色
 * @param dasharray
 * @param id dom id
 */
function createLine(width, color, dasharray, id) {
  return that.dm.defaultGroup.line(0, 0, 0, 0).stroke({
    width: width,
    color: color,
    dasharray: dasharray
  }).attr({
    id: id
  });
}

/**
 * 生成大的矩形框
 * @param loader img信息
 * @param data 参数信息
 */
function createImgRect(loader, data) {
  // that.dm.defaultGroup.rect(loader.width, loader.height).fill('none').stroke(data).attr({id: 'image-border'});
  var width = loader.width || 0,
    height = loader.height || 0,
    point;
  // that.dm.defaultGroup.rect(loader.width, loader.height).fill('none').stroke(data).attr({id: 'image-border'});
  point = [
    [0, 0],
    [width, 0],
    [width, height],
    [0, height]
  ];
  that.dm.defaultGroup.polygon(point).fill('none').stroke(data).attr({
    id: 'image-border'
  });
  // console.log('初始化绘制多边形边框', data, loader);
}

/**
 * 生成一个矩形对象并返回
 * @param data 点的信息
 * @param id 元素id
 * @param color 元素颜色
 * @param opacity 元素透明度
 */
function createRect(data, id, color, opacity) {
  return that.dm.defaultGroup.rect(0, 0).move(data.rx, data.ry).fill({
    color: color,
    opacity: opacity
  }).attr({
    id: id,
    class: 'area-box'
  }) // .data('startPoint',{rx:lastPoint.rx,ry:lastPoint.ry});
}

/**
 * 校验方法
 * @param condition 条件
 * @param msg 提示消息
 */
function assert(condition, msg) {
  if (!condition) throw new Error('abkOcr:' + msg)
}

/**
 * warn提示
 * @param msg
 */
function warnInfo(msg) {
  console.warn(msg)
}

/**
 * 点的转化
 * @param data
 * @returns {*}
 */
function pointjrx(data) {
  var type = typeof data,
    info = [],
    arr, numArr;
  if (type === 'object') {
    return data;
  } else if (type === 'string') {
    arr = data.split(' ');
    for (var i = 0; i < arr.length; i++) {
      numArr = arr[i].split(',');
      info.push([Number(numArr[0]), Number(numArr[1])])
    }
    return info
  }
}

/**
 * 求两条线段的交点
 * @param a
 * @param b
 * @param c
 * @param d
 * @param type
 * @returns {*}
 */
function segmentsIntr(a, b, c, d, type) {
  // console.log('a, b, c, d , type',a, b, c, d , type,b.y - a.y);
  //线段ab的法线N1
  var nx1 = (b.y - a.y),
    ny1 = (a.x - b.x);
  //线段cd的法线N2
  var nx2 = (d.y - c.y),
    ny2 = (c.x - d.x);
  //两条法线做叉乘, 如果结果为0, 说明线段ab和线段cd平行或共线,不相交
  var denominator = nx1 * ny2 - ny1 * nx2;

  if (denominator == 0) {
    return false;
  }
  //在法线N2上的投影
  var distC_N2 = nx2 * c.x + ny2 * c.y;
  var distA_N2 = nx2 * a.x + ny2 * a.y - distC_N2;
  var distB_N2 = nx2 * b.x + ny2 * b.y - distC_N2;
  // 点a投影和点b投影在点c投影同侧 (对点在线段上的情况,本例当作不相交处理);
  if (distA_N2 * distB_N2 >= 0) {
    return false;
  }
  //判断点c点d 和线段ab的关系, 原理同上
  //在法线N1上的投影
  var distA_N1 = nx1 * a.x + ny1 * a.y;
  var distC_N1 = nx1 * c.x + ny1 * c.y - distA_N1;
  var distD_N1 = nx1 * d.x + ny1 * d.y - distA_N1;
  if (distC_N1 * distD_N1 >= 0) {
    return
    false;
  }
  //计算交点坐标
  var fraction = distA_N2 / denominator;
  var dx = fraction * ny1,
    dy = -fraction * nx1;
  return {
    x: a.x + dx,
    y: a.y + dy
  };
}

/**
 * 求距离起止点最近的交点s
 * @param point 当前点
 * @param horizonPoint 数组
 */
function sumNearPoint(point, horizonPoint) {
  var nearPoint = {
    x: '',
    y: ''
  };
  horizonPoint.forEach(function (k, v) {
    if (!nearPoint.x || (Math.abs(point[0] - k.x) < Math.abs(point[0] - nearPoint.x))) {
      nearPoint = k
    }
  });
  return nearPoint;
}

/**
 * 根据 缩放比例 修改图形的边框
 * @param element
 */
function changeStrokeByZoom(element) {
  try {
    element.each(function (i, children) {
      var type = this.type,
        zoom = that.vm.zoom,
        strokeWidth = that.vm.strokeWidth,
        dragPointSize = that.vm.dragPointSize,
        initTextSize = that.vm.textSize,
        width = 2,
        circleWidth = 10,
        textSize = 12;

      if (type === 'g') {
        changeStrokeByZoom(this);
      } else if (type !== 'g' && this.type !== 'circle' && this.type !== 'text') {
        width = strokeWidth / zoom;
        if (width > strokeWidth) {
          width = strokeWidth;
        }
        this.stroke({
          width: width
        })
      } else if (type === 'circle' && this.attr('class').indexOf('adjust-size') > -1) {
        var svgImg = document.getElementById('svgImage');
        svgImgW = svgImg.getBoundingClientRect().width;
        var adjustSize = '';
        if (svgImgW < 180) {
          adjustSize = 30;
        } else {
          adjustSize = dragPointSize / zoom;
        }
        // if ($ > dragPointSize) { adjustSize = dragPointSize; }
        this.size(adjustSize)
      } else if (type === 'circle') {
        circleWidth = dragPointSize / zoom;
        if (circleWidth > dragPointSize) {
          circleWidth = dragPointSize;
        }
        this.size(circleWidth)
      } else if (type === 'text') {
        textSize = initTextSize / zoom;
        if (textSize > initTextSize) {
          textSize = initTextSize
        }
        this.font({
          size: textSize
        })
      }
    })
  } catch (e) {
    warnInfo(e);
  }
}

/**
 * 判断顺序多点变形 绘制方向 顺时针or逆时针
 * @param portArr 多边形点阵坐标集合 [[x1,y1],[x2,y2]...] 
 * 结果 > 0 顺时针
 * 结果 < 0 逆时针
 * 结果 = 0 共线
 */
function getPolygonDirection(portArr) {
  // 方法1 
  var gluten = 0;
  portArr.forEach(function (p, i, item) {
    var A = p,
      B = item[i + 1],
      C = item[i + 2];

    if ((i + 2) <= portArr.length - 1) {
      gluten += (C[0] - B[0]) * (A[1] - B[1]) - (C[1] - B[1]) * (A[0] - B[0])
    }
    // if (item[i + 1]) {
    //   gluten += (p[0] * item[i + 1][1]) - (p[1] * item[i + 1][0])
    // }
  })
  return gluten

  // 方法2
  // var p = {
  //   val : 0,
  //   ind : 0
  // },
  // lastInd = 0,
  // nextInd = 0;
  // portArr.forEach(function(ports, ind){
  //   if(ports[0] > p.val) {
  //     p.val = ports[0]
  //     p.ind = ind
  //   }
  // })
  // lastInd = p.ind - 1;
  // nextInd = p.ind + 1;
  // if(p.ind === 0){
  //   lastInd = portArr.length - 1;
  // }
  // if(p.ind === portArr.length - 1){
  //   nextInd = 0;
  // }
  // var lastPort = portArr[lastInd],
  //     nextPort = portArr[nextInd];
  // return (lastPort[0] * nextPort[1]) - (lastPort[1] * nextPort[0])

}

// global.OcrPublicClass = OcrPublicClass;

export default OcrPublicClass
